存儲過程record
⑴ sql存儲過程:exec sp_executesql @sqlRecord ,N'@recordCount int output',@recordCount output;的意思
執行動態SQL ,具體可以查看sp_executesql 的幫助
⑵ postgresql存儲過程 怎麼實現無返回值
PostgreSQL 存儲過程定義格式如下:
■結構 PL/pgSQL是一種塊結構的語言,比較方便的是用pgAdmin III新建Function,填入一些參數就可以了。
基本上是這樣的:
CREATE OR REPLACE FUNCTION 函數名(參數1,[整型 int4, 整型數組 _int4, ...]) RETURNS 返回值類型 AS $BODY$ DECLARE 變數聲明 BEGIN 函數體 END; $BODY$ LANGUAGE 『plpgsql』 VOLATILE;
■變數類型 除了postgresql內置的變數類型外,常用的還有 RECORD ,表示一條記錄。
■賦值 賦值和Pascal有點像:「變數 := 表達式;」 有些奇怪的是連接字元串的是「||」,比如 sql := 『SELECT * FROM』 || table || 『WHERE …』;
■判斷 判斷又和VB有些像: IF 條件 THEN … ELSEIF 條件 THEN … ELSE … END IF;
■循環 循環有好幾種寫法: WHILE expression LOOP statements END LOOP; 還有常用的一種是:(從1循環到9可以寫成FOR i IN 1..9 LOOP) FOR name IN [ REVERSE ] expression .. expression LOOP statements END LOOP;
■其他 還有幾個常用的函數: SELECT INTO record …; 表示將select的結果賦給record變數(RECORD類型) PERFORM query; 表示執行query並丟棄結果 EXECUTE sql; 表示執行sql語句,這條可以動態執行sql語句(特別是由參數傳入構造sql語句的時候特別有用)
--簡單的例子:
例1:無返回值
CREATE OR REPLACE FUNCTION 函數名稱( 參數1,參數2,...)
AS
$BODY$
DECLARE --定義
BEGIN
INSERT INTO "表名" VALUES(參數1,參數2,...);
END
$BODY$
LANGUAGE 'plpgsql' VOLATILE; -- 最後別忘了這個。
例2:有返回值
CREATE OR REPLACE FUNCTION 函數名稱(deptcode VARCHAR(20) ,deptname VARCHAR(60) ,pycode VARCHAR(60),isenabled CHAR(1))
RETURNS BOOLEAN --返回值,布爾類型
AS
$body$
DECLARE
deptcode VARCHAR(20);
deptname VARCHAR(60);
pycode VARCHAR(60);
isenabled CHAR(1);
BEGIN
UPDATE "deptDict" SET deptcode=deptcode,deptname=deptname,pycode=pycode,isenabled=isenabled,updatedhisdatetime=CURRENT_TIMESTAMP
WHERE deptcode=deptcode;
RETURN TRUE;
END
$body$
LANGUAGE 'plpgsql' VOLATILE;
最後再加上如何執行這個存儲過程(函數)
-- 執行存儲過程方法1
SELECT * FROM 函數名稱(參數1,參數2,...)
-- 執行存儲過程方法2
SELECT 函數名稱('0參數1,參數2,...)
⑶ 存儲過程如何使用
問題一:SQL 中存儲過程怎麼使用? sql存儲過程及應用
一、簡介:
存儲過程(Stored Procere), 是一組為了完成特定功能的SQL 語句,集經編譯後
存儲在資料庫中,用戶通過指定存儲過程的名字並給出參數,如果該存儲過程帶有參數來執行
它,
在SQL Server 的系列版本中,存儲過程分為兩類:系統提供的存儲過程和用戶自定義存儲過程
。
系統SP,主要存儲master 資料庫中,並以sp_為前綴並且系統存儲過程主要是從系統表中獲取
信息,從而為系統管理員管理SQL Server。用戶自定義存儲過程是由用戶創建,並能完成
某一特定功能,如:查詢用戶所需數據信息的存儲過程。
存儲過程具有以下優點
1.存儲過程允許標准組件式編程(模塊化設計)
存儲過程在被創建以後,可以在程序中被多次調用,而不必重新編寫該存儲過程的SQL語句,而
且數
據庫專業人員可隨時對存儲過程進行修改,但對應用程序源代碼毫無影響。因為應用程序源代
碼只包含存
儲過程的調用語句,從而極大地提高了程序的可移植性。
2.存儲過程能夠實現快速的執行速度
如果某一操作包含大量的Transaction-SQL 代碼,,或分別被多次執行,那麼存儲過程要比批處理
的
執行速度快很多,因為存儲過程是預編譯的,在首次運行一個存儲過程時,查詢優化器對其進
行分析優
化,並給出最終被存在系統表中的執行計劃,而批處理的Transaction-SQL 語句在每次運行時
都要進行
編譯和優化,因此速度相對要慢一些。
3.存儲過程能夠減少網路流量
對於同一個針對數據資料庫對象的操作,如查詢修改,如果這一操作所涉及到的Transaction-SQL
語句被組織成一存儲過程,那麼當在客戶計算機上調用該存儲過程時,網路中傳送的只是該調
用語句,否
則將是多條SQL 語句從而大大增加了網路流量降低網路負載。
4.存儲過程可被作為一種安全機制來充分利用
系統管理員通過,對執行某一存儲過程的許可權進行限制,從而能夠實現對相應的數據訪問許可權的
限
制。
二、變數
@I
三、流程式控制制語句(if else | select case | while )
Select ... CASE 實例
DECLARE @iRet INT, @PKDisp VARCHAR(20)
SET @iRet = '1'
Select @iRet =
CASE
WHEN @PKDisp = '一' THEN 1
WHEN @PKDisp = '二' THEN 2
WHEN @PKDisp = '三' THEN 3
WHEN @PKDisp = '四' THEN 4
WHEN @PKDisp = '五' THEN 5
ELSE 100
END
四、存儲過程格式
創建存儲過程
Create Proc dbo.存儲過程名
存儲過程參數
AS
執行語句
RETURN
執行存儲過程
GO
*********************************************************/
-- 變數的聲明,sql裡面聲明變數時必須在變數前加@符號
DECLARE @I INT
-- 變數的賦值,變數賦值時變數前必須加set
SET @I = 30
-- 聲明多個變數
DECLARE @s varchar(10),@a INT
-- Sql 里if語句
IF 條件 BEGIN
執行語句
END
ELSE BEGIN
......>>
問題二:為什麼要使用存儲過程? 幾個去 IBM 面試的兄弟回來抱怨:去了好幾個不同的 IBM項目組,幾乎每個面試官問到資料庫的時候都要問用沒用過存儲過程,煩人不?大家去面的程序員,又不是筆者認為,存儲過程說白了就是一堆 SQL 的合並。中間加了點邏輯控制。但是存儲過程處理比較復雜的業務時比較實用。比如說,一個復雜的數據操作。如果你在前台處理的話。可能會涉及到多次資料庫連接。但如果你用存儲過程的話。就只有一次。從響應時間上來說有優勢。也就是說存儲過程可以給我們帶來運行效率提高的好處。另外,程序容易出現 BUG數據量小的,或者和錢沒關系的項目不用存儲過程也可以正常運作。mysql 的存儲過程還有待實際測試。如果是正式項目,建議你用 sqlserver 或 oracle的存儲過程。數據與數據之間打交道的話,過程會比程序來的快的多。面試官問有沒有用存儲,實際上就是想知道前來面試的程序員到底做過數據量大的項目沒。如果是培訓出來的,或者小項目小公司出來的,對存儲肯定接觸的少了。所以,要想進大公司,沒有豐富存儲過程經驗,是不行的。錯。存儲過程不僅僅適用於大型項目,對於中小型項目,使用存儲過程也是非常有必要的。其威力和優勢主要體現在:1.存儲過程只在創造時進行編譯,以後每次執行存儲過程都不需再重新編譯,而一般 SQL語句每執行一次就編譯一次,所以使用存儲過程可提高資料庫執行速度。2.當對資料庫進行復雜操作時(如對多個表進行Update,Insert,Query,Delete時),可將此復雜操作用存儲過程封裝起來與資料庫提供的事務處理結合一起使用。這些操作,如果用程序來完成,就變成了一條條的 SQL語句,可能要多次連接資料庫。而換成存儲,只需要連接一次資料庫就可以了。3.存儲過程可以重復使用,可減少資料庫開發人員的工作量。4.安全性高,可設定只有某此用戶才具有對指定存儲過程的使用權。存儲過程的缺點1:調試麻煩,但是用 PL/SQL Developer 調試很方便!彌補這個缺點。 2:移植問題,資料庫端代碼當然是與資料庫相關的。但是如果是做工程型項目,基本不存在移植問題。 3:重新編譯問題,因為後端代碼是運行前編譯的,如果帶有引用關系的對象發生改變時,受影響的存儲過程、包將需要重新編譯(不過也可以設置成運行時刻自動編譯)。4:如果在一個程序系統中大量的使用存儲過程,到程序交付使用的時候隨著用戶需求的增加會導致數據結構的變化,接著就是系統的相關問題了,最後如果用戶想維護該系統可以說是很難很難、而且代價是空前的。維護起來更加麻煩!
問題三:oracle中的存儲過程,有什麼作用,以及怎麼在代碼中使用? 樓上也不知道從哪扒下來的,一看LZ就是初學,舉點例子不行嗎?
比如建立個測試表
create table test(id int,name varchar2(10),counts int); insert into test values (1,'張三',100);insert into test values (2,'李四',200); mit;
現在給你出個題目是
查詢所有人加在一起的counts是多少
創建存儲過程
create or replace p_test --創建存儲過程,asv_counts int;--定義變數begin --開始select sum(counts) into v_counts from test;--將得到的結果放到變數里DBMS_OUTPUT.PUT_LINE(v_counts);--將結果列印輸出end;--結束
執行這種不帶輸入參數的
begin p_test;end;
然後你檢查下結果
再給你創建一個帶輸入參數的
題目是,查詢id為1的人名是什麼
create or replace p_test1(v_id int)asv_name varchar2(10);beginselect name into v_name from test where id=v_id;DBMS_OUTPUT.PUT_LINE(v_name);end;
執行時這樣
beginp_test1(1);end;
第2個我沒給你寫注釋,你看你自己應該能理解吧
補充一下,存儲過程不一定只是執行查詢,也可以做刪除或者修改等sql語句,總體來說就是幾個或N個sql語句的 *** ,來完成系統內某些特定的需求,這些需求可以是一個sql搞定的,也可以是多個sql組合的
問題四:SQL 存儲過程建立和使用方法? Sql Server的存儲過程是一個被命名的存儲在伺服器上的Transacation-Sql語句 *** ,是封裝重復性工作的一種方法,它支持用戶聲明的變數、條件執行和其他強大的編程功能。 存儲過程相對於其他的資料庫訪問方法有以下的優點: (1)重復使用。存儲過程可以重復使用,從而可以減少資料庫開發人員的工作量。 (2)提高性能。存儲過程在創建的時候就進行了編譯,將來使用的時候不用再重新編譯。一般的SQL語句每執行一次就需要編譯一次,所以使用存儲過程提高了效率。 (3)減少網路流量。存儲過程位於伺服器上,調用的時候只需要傳遞存儲過程的名稱以及參數就可以了,因此降低了網路傳輸的數據量。 (4)安全性。參數化的存儲過程可以防止SQL注入式的攻擊,而且可以將Grant、Deny以及Revoke許可權應用於存儲過程。 存儲過程一共分為了三類:用戶定義的存儲過程、擴展存儲過程以及系統存儲過程。 其中,用戶定義的存儲過程又分為Transaction-SQL和CLR兩種類型。 Transaction-SQL 存儲過程是指保存的Transaction-SQL語句 *** ,可以接受和返回用戶提供的參數。 CLR存儲過程是指對.Net Framework公共語言運行時(CLR)方法的引用,可以接受和返回用戶提供的參數。他們在.Net Framework程序集中是作為類的公共靜態方法實現的。(本文就不作介紹了) 創建存儲過程的語句如下:Code
CREATE { PROC | PROCEDURE } [schema_name.] procere_name [ ; number ]
[ { @parameter [ type_schema_name. ] data_type }
[ VARYING ] [ = default ] [ [ OUT [ PUT ]
] [ ,n ]
[ WITH [ ,n ]
[ FOR REPLICATION ]
AS { [;][ n ] | }
[;]
::=
[ ENCRYPTION ]
[ REPILE ]
[ EXECUTE_AS_Clause ]
::=
{ [ BEGIN ] statements [ END ] }
::=
EXTERNAL NAME assembly_name.class_name.method_name [schema_name]: 代表的是存儲過程所屬的架構的名稱 例如: Create Schema yangyang8848
Go
Create Proc yangyang8848.AllGoods
As Select * From Master_Goods
Go 執行:Exec AllGoods 發生錯誤。 執......>>
問題五:資料庫中的存儲過程怎麼用 啊!!求解..... 10分 關鍵字:procere
例子:
SQL> create [or replace] procere procere_name is
begin
--開始執行
insert into test('10001','Visket');
end;
/
以上操作就能為test表添加一條信息
執行存儲過程procere用的命令是exec
記住存儲過程中,語句結尾一定要有分號
問題六:存儲過程是多用還是少用? 做項目的時候我們有時候會面臨一個選擇,我們到底是應該多寫存儲過程還是少寫存儲過程了?這個問題的爭論也是由來已久,在不同的公司以及不同的技術負責人那裡往往會得到不同的答案。在實際項目中我們最後所採取的方式,往往不外乎以下三種方式。
第一種方式是要求所有資料庫操作不使用任何的存儲過程,所有操作都採用標准sql語句來完成,即便是一個動作需要完成多步資料庫操作,也不使用任何存儲過程,而是在程序代碼中採用事務的方式來完成;第二種方式就是就要求所有的資料庫操作都用存儲過程封裝起來,哪怕是一個最簡單的insert 操作。在程序代碼看不到一行 sql語句,如果採用分工合作的方式,程序員甚至都可以不懂sql語法。第三種方式是一般相對簡單的資料庫操作採用標准sql語句來完成,一些相對比較復雜的商務邏輯用存儲過程來完成。
當然系統如果採用了hibernate或nhibernate之類的框架,不需要寫sql語句的時候,我想還是應該屬於第三種方式,因為在開發的時候hibernate框架允許我們在適當的時候,拋開其框架自己寫存儲過程和sql語句來完成資料庫操作。其實這三種方式都各有所長,也各有不足。
第一種方式是所有的資料庫操作都採用標准sql語句來完成的方式,在程序的執行效率上是肯定不如後面兩種方式,系統如果是一個大型的ERP,這種方式就是絕對不可取的。因為在開發基本結束後,系統如果需要優化或者希望得到優化時,那對開發人員來說就是一件非常麻煩的事情了,因為優化的重點基本上都是集中資料庫操作上,開發人員所能做的就是一個個sql語句去檢查,是不是還能進一步優化,尤其是一些相對比較復雜的查詢語句是我們所檢查的重點。分頁顯示就是一個典型的存儲過程提高程序效率的例子。如果使用存儲過程來進行分頁操作,就是利用存儲過程從系統中提取我們所需要的記錄集,分頁的效率就大大提高了。反過來如果我們不用存儲過程進行分頁操作,是利用sql語句的方式把所有記錄集都讀入內存中,然後再從內存中獲取我們所需要的記錄 *** ,這樣分頁效率自然就降低了。當然利用sql語句也能得到我們所需要的記錄,而不是所有記錄,但是那樣麻煩多了,不在我們討論范圍之內。
這種方式另外還有一個不足之處,一個系統或一個項目總會或多或少地存在有一些容易變化而又復雜的商務邏輯,如果把這些復雜的商務邏輯封裝到存儲過程中,商務邏輯的變化都只涉及存儲過程變化,而與程序代碼不 *** ,那麼不用存儲過程太可惜了。
這種方式雖然有不足,但是一旦採用這種方式的話,我們如果對該項目進行資料庫移植的時候,開發人員就會覺得當時的決策人是多麼的偉大與英明。而且我們知道access和mysql的以前版本是不提供存儲過程支持的,所有一些中小項目在這個方面的選擇往往也是不得已而為之。不用存儲過程有一個優點,調試代碼的時候沒有存儲過程可是要方便很多很多的哦,所以在很多很多的項目中都是採用標準的sql語句而不使用任何的存儲過程。這可是大多程序員用標准sql而不用存儲過程的直接原因,說白了,就是嫌麻煩。
第二種方式是所有的資料庫操作全部採用存儲過程封裝的方式,如果採用這種方式,程序的執行效率相對要高,尤其面對在一些復雜的商務邏輯時候,不僅在效率方面有明顯的提高,而且當商務邏輯發生變化時,我們開發人員做相應的修改的時候,往往都不用修改程序代碼,僅僅修改存儲過程就能滿足系統變化了。
還有一個好處就是當我們開發好的一個系統後,如果發現一種模式或語言在某些方面難以滿足需求時,我們就可以很快的用兩外一種語言來重新開發,那個時候就非常方便了。比如在02年中科院下屬的一個公司就用ASP開......>>
問題七:在SQL中存儲過程的一般語法是什麼? sql server存儲過程語法
存儲過程就是作為可執行對象存放在資料庫中的一個或多個SQL命令。
定義總是很抽象。存儲過程其實就是能完成一定操作的一組SQL語句,只不過這組語句是放在資料庫中的(這里我們只談SQL Server)。如果我們通過創建存儲過程以及在ASP中調用存儲過程,就可以避免將SQL語句同ASP代碼混雜在一起。這樣做的好處至少有三個:
第一、大大提高效率。存儲過程本身的執行速度非常快,而且,調用存儲過程可以大大減少同資料庫的交互次數。
第二、提高安全性。假如將SQL語句混合在ASP代碼中,一旦代碼失密,同時也就意味著庫結構失密。
第三、有利於SQL語句的重用。
在ASP中,一般通過mand對象調用存儲過程,根據不同情況,本文也介紹其它調用方法。為了方便說明,根據存儲過程的輸入輸出,作以下簡單分類:
1. 只返回單一記錄集的存儲過程
假設有以下存儲過程(本文的目的不在於講述T-SQL語法,所以存儲過程只給出代碼,不作說明):
/*SP1*/
CREATE PROCEDURE dbo.getUserList
as
set nocount on
begin
select * from dbo.[userinfo]
end
go
以上存儲過程取得userinfo表中的所有記錄,返回一個記錄集。通過mand對象調用該存儲過程的ASP代碼如下:
'**通過mand對象調用存儲過程**
DIM Mym,MyRst
Set Mym = Server.CreateObject(ADODB.mand)
Mym.ActiveConnection = MyConStr 'MyConStr是資料庫連接字串
Mym.mandText = getUserList '指定存儲過程名
Mym.mandType = 4 '表明這是一個存儲過程
Mym.Prepared = true '要求將SQL命令先行編譯
Set MyRst = Mym.Execute
Set Mym = Nothing
存儲嘩程取得的記錄集賦給MyRst,接下來,可以對MyRst進行操作。
在以上代碼中,mandType屬性表明請求的類型,取值及說明如下:
-1 表明mandText參數的類型無法確定
1 表明mandText是一般的命令類型
2 表明mandText參數是一個存在的表名稱
4 表明mandText參數是一個存儲過程的名稱
還可以通過Connection對象或Recordset對象調用存儲過程,方法分別如下:
'**通過Connection對象調用存儲過程**
DIM MyConn,MyRst
Set MyConn = Server.CreateObject(&qu......>>
問題八:如何使用Oracle存儲過程的一個簡單例子 樓主您好
---創建表
create table TESTTABLE
(
id1 VARCHAR2(12),
name VARCHAR2(32)
)
select t.id1,t.name from TESTTABLE t
insert into TESTTABLE (ID1, NAME)
values ('1', 'zhangsan');
insert into TESTTABLE (ID1, NAME)
values ('2', 'lisi');
insert into TESTTABLE (ID1, NAME)
values ('3', 'wangwu');
insert into TESTTABLE (ID1, NAME)
values ('4', 'xiaoliu');
insert into TESTTABLE (ID1, NAME)
values ('5', 'laowu');
---創建存儲過程
create or replace procere test_count
as
v_total number(1);
begin
select count(*) into v_total from TESTTABLE;
DBMS_OUTPUT.put_line('總人數:'||v_total);
end;
--准備
--線對scott解鎖:alter user scott account unlock;
--應為存儲過程是在scott用戶下。還要給scott賦予密碼
---alter user scott identified by tiger;
---去命令下執行
EXECUTE test_count;
----在ql/spl中的sql中執行
begin
-- Call the procere
test_count;
end;
create or replace procere TEST_LIST
AS
---是用游標
CURSOR test_cursor IS select t.id1,t.name from TESTTABLE t;
begin
for Test_record IN test_cursor loop---遍歷游標,在列印出來
DBMS_OUTPUT.put_line(Test_record.id1||Test_record.name);
END LOOP;
test_count;--同時執行另外一個存儲過程(TEST_LIST中包含存儲過程test_count)
end;
-----執行存儲過程TEST_LIST
begin
TEST_LIST;
END;
---存儲過程的參數
---IN 定義一個輸入參數變數,用於傳遞參數給存儲過程
--OUT 定義一個輸出參數變數,用於從存儲過程獲取數據
---IN OUT 定義一個輸入、輸出參數變數,兼有以上兩者的功能
......>>
問題九:如何使用sql語句查看存儲過程 --下面這條語句可以查看存儲過程具體代碼exec sp_helptext 存儲過程名--下面這條語句查看資料庫中有哪些存儲過程select * from sysobjects where type='P'
問題十:存儲過程中怎麼使用row 一般分為十種情況,每種語法各不相同: 1、 創建語法create proc | procere pro_name [{@參數數據類型} [=默認值] [output], {@參數數據類型} [=默認值] [output], .... ]as SQL_statements2、 創建不帶參數存儲過程--創建存儲過程if (exists (select * from sys.objects where name = 'proc_get_student')) drop proc proc_get_studentgocreate proc proc_get_studentas select * from student;--調用、執行存儲過程exec proc_get_student;3、 修改存儲過程--修改存儲過程alter proc proc_get_studentasselect * from student;4、 帶參存儲過程--帶參存儲過程if (object_id('proc_find_stu', 'P') is not null) drop proc proc_find_stugocreate proc proc_find_stu(@startId int, @endId int)as select * from student where id between @startId and @endIdgoexec proc_find_stu 2, 4;5、 帶通配符參數存儲過程--帶通配符參數存儲過程if (object_id('proc_findStudentByName', 'P') is not null) drop proc proc_findStudentByNamegocreate proc proc_findStudentByName(@name varchar(20) = '%j%', @nextName varchar(20) = '%')as select * from student where name like @name and name like @nextName;goexec proc_findStudentByName;exec proc_findStudentByName '%o%', 't%';6、 帶輸出參數存儲過程if (object_id('proc_getStudentRecord', 'P') is not null) drop proc proc_getStudentRecordgocreate proc proc_getStudentRecord( @id int, --默認輸入參數 @name varchar(20) out, --輸出參數 @age varchar(20) output--輸入輸出參數)as select @name = name, @age = age from student where id = @id and sex = @age;go-- declare @id int, @name varchar(20), @temp varchar(20)......>>
⑷ mysql 存儲過程中的查詢語句無法查詢到數據
一條語句實現的方法不如存儲過程方便,而且不如存儲過程效率高,樓主寫個存儲過程會比較好
INSERT INTO log (date, ip) SELECT '2014-01-01' as date, '192.168.1.1' as ip FROM log WHERE NOT EXISTS ( SELECT * FROM log t WHERE t.data = '2014-01-01' AND t.ip = '192.168.1.1')
⑸ 在存儲過程中怎樣遍歷表
一條語句迅好就世燃可搜昌虛以
update table_to set [name]=update_from.[name] from update_from where update_to.id=update_from.id
⑹ Postgres-存儲過程 return 詳解
https://www.cnblogs.com/Thenext/p/13531947.html
如果返回一個 數字或者字元 比較簡單,那麼多行多列怎麼辦呢,分為以下幾種情況【東西很多,這里只做簡單列舉】
返回多行單列
又分為幾種方式
1. return next,用在 for 循環中
( in_idinteger)RETURNSSETOFvarcharas $$DECLARE v_name varchar;BEGINforv_namein( (selectnamefromtest_result1whereid=in_id)union(selectnamefromtest_result2whereid= in_id) ) loop
RETURNNEXT v_name;
end loop;
return;END;
$$
LANGUAGE PLPGSQL;
注意
1. 循環外還有個 return
2. 需要實現聲明 v_name
2. return query,無需 for 循環
( in_idinteger)RETURNSSETOFvarcharas $$DECLARE v_rec RECORD;BEGINreturnquery ( (selectnamefromtest_result1whereid=in_id)union(selectnamefromtest_result2whereid= in_id) );
return;END;$$LANGUAGE PLPGSQL;
注意:如果 返回類型為 setof,最好用如下方法
RETURNQUERYEXECUTESQL
不要這么用
executesqlinto out;returnout;
返回多行多列
也有多種方式
1. 使用 return next 和 setof record ,需要 for 循環
( in_idinteger)RETURNSSETOF RECORDas $$DECLARE v_rec RECORD; BEGINforv_recin( (selectid , namefromtest_result1whereid=in_id)union(selectid , namefromtest_result2whereid= in_id) )loop
RETURNNEXT v_rec;
end loop;
return;END;
$$
LANGUAGE PLPGSQL;
注意
1. 讀取表的整行數據時才能用 record
2. 如果讀取的數據不是整行,需要自定義 復合數據類型,否則會報如下錯誤
ERROR: acolumndefinition listisrequiredforfunctions returning "record"
定義復合類型 ,示例如下
createtype myout2as (
road_num int,
freq bigint);createorreplacefunctiontest(cartext, time1text, time2text)returnssetof myout2as $$declare
array1 text[];
array2 text[];
len1 integer;
len2 integer;
x integer;
y integer;
road_str text;
car_str text;
sql text;
i myout2;
begin-- vin 號拼接selectregexp_split_to_array(car,',')into array2;
selectarray_length(array2,1)into len2;
car_str :='';
y :=1;
whiley<= len2 loop
car_str :=car_str||quote_literal(array2[y])||',';
y :=y+1;
end loop;
-- sql 拼接sql :='select road_number, sum(frequency) from heat_map where date_key >= '''|| time1
||'-01'' and date_key <='''|| time2
||'-20'' and vin in ('||rtrim(car_str,',')
||')group by road_number;';
--execute sql into out;foriinexecute sql loop
returnnext i;
end loop;
return;end$$ language plpgsql;
在執行時可能會報如下錯誤
ERROR:set-valuedfunctioncalledincontext that cannot accept aset
解決方法
select funcname(arg);--改為select*fromfuncname(arg);
2. return query,無需 for 循環
( in_idinteger)RETURNSSETOF RECORDas $$DECLARE v_rec RECORD;BEGINreturnquery ( (selectid , namefromtest_result1whereid=in_id)union(selectid , namefromtest_result2whereid= in_id) );
return;END;
$$
LANGUAGE PLPGSQL;
3. 使用 out 輸出參數
( in_idinteger,out o_idinteger,out o_namevarchar)
RETURNSSETOF RECORDas $$DECLARE v_rec RECORD;BEGINforv_recin( (selectid , namefromtest_result1whereid=in_id)union(selectid , namefromtest_result2whereid= in_id) )loop
o_id := v_rec.id;
o_name := v_rec.name;
RETURNNEXT ;
end loop;
return;END;
$$
LANGUAGE PLPGSQL;
總結 - return next && return query
我們可以看到上面無論是單列多行還是多列多行,都用到了 return next 和 return query 方法
在 plpgsql 中,如果存儲過程返回 setof sometype,則返回值必須在 return next 或者 return query 中聲明,然後有一個不帶參數的 retrun 命令,告訴函數執行完畢;【setof 就意味著 多行】
用法如下
RETURNNEXT expression;RETURN QUERY query;RETURNQUERYEXECUTEcommand-string[ USING expression [, ... ]];
return next 可以用於標量和復合類型數據;
return query 命令將查詢到的一條結果追加到函數的結果集中;
二者在單一集合返回函數中自由混合,在這種情況下,結果將被級聯。【有待研究】
return query execute 是 return query 的變形,它指定 sql 將被動態執行;
returnqueryselectroad_number,sum(frequency)fromheat_mapgroupbyroad_number;--這樣可以sql :='select road_number, sum(frequency) from heat_map group by road_number';returnquery sql;--這樣不行
參考資料:
https://blog.csdn.net/victor_ww/article/details/44415895postgresql自定義類型並返回數組
https://blog.csdn.net/weixin_42767321/article/details/92992935PG return next & return query
https://blog.csdn.net/luojin/article/details/45487373PostgreSQL function返回多列多行
https://www.cnblogs.com/xiongsd/archive/2013/06/05/3118704.html返回結果集多列和單列的例子
https://www.cnblogs.com/lottu/p/7404722.html PostgreSQL存儲過程(1)-基於SQL的存儲過程
https://blog.csdn.net/pg_hgdb/article/details/79692749Postgresql動態SQL
https://stackoverflow.com/questions/40864464/postgresql-pgadmin-error-return-cannot-have-a-parameter-in-function-returning-s/40864898 postgresql, pgadmin error RETURN cannot have a parameter in function returning set
https://blog.csdn.net/qq_42535651/article/details/92089510postgresql存儲過程輸出參數
https://www.cnblogs.com/winkey4986/p/6437811.html
https://www.cnblogs.com/lottu/p/7405829.html PostgreSQL存儲過程(3)-流程式控制制語句
⑺ pl/sql存儲過程返回record類型的結果,java里如何調用呢
用object,不用桐好record.
object SQL支持,record屬於沒昌PL/SQL。
給你一個TOM的枯輪扒例子:
1. create or replace type myScalarType
as object (x int,y varchar2(20),z date,
member function get_Y(x int) return varchar2);
2 .create or replace type myTableType as table of myScalarType;
3. create or replace function non_pipelined( p_like in varchar2 )
return myTableType
as
l_data myTableType;
begin
select myScalarType(user_id, username, created)
BULK COLLECT into l_data
from all_users
where username like p_like;
return l_data;
end;
4.select * from TABLE( non_pipelined( '%A%' ) );
⑻ 在SQL中存儲過程的一般語法是什麼
sql server存儲過程語法
存儲過程就是作為可執行對象存放在資料庫中的一個或多個SQL命令。
定義總是很抽象。存儲過程其實就是能完成一定操作的一組SQL語句,只不過這組語句是放在資料庫中的(這里我們只談SQL Server)。如果我們通過創建存儲過程以及在ASP中調用存儲過程,就可以避免將SQL語句同ASP代碼混雜在一起。這樣做的好處至少有三個:
第一、大大提高效率。存儲過程本身的執行速度非常快,而且,調用存儲過程可以大大減少同資料庫的交互次數。
第二、提高安全性。假如將SQL語句混合在ASP代碼中,一旦代碼失密,同時也就意味著庫結構失密。
第三、有利於SQL語句的重用。
在ASP中,一般通過command對象調用存儲過程,根據不同情況,本文也介紹其它調用方法。為了方便說明,根據存儲過程的輸入輸出,作以下簡單分類:
1. 只返回單一記錄集的存儲過程
假設有以下存儲過程(本文的目的不在於講述T-SQL語法,所以存儲過程只給出代碼,不作說明):
/*SP1*/
CREATE PROCEDURE dbo.getUserList
as
set nocount on
begin
select * from dbo.[userinfo]
end
go
以上存儲過程取得userinfo表中的所有記錄,返回一個記錄集。通過command對象調用該存儲過程的ASP代碼如下:
'**通過Command對象調用存儲過程**
DIM MyComm,MyRst
Set MyComm = Server.CreateObject("ADODB.Command")
MyComm.ActiveConnection = MyConStr 'MyConStr是資料庫連接字串
MyComm.CommandText = "getUserList" '指定存儲過程名
MyComm.CommandType = 4 '表明這是一個存儲過程
MyComm.Prepared = true '要求將SQL命令先行編譯
Set MyRst = MyComm.Execute
Set MyComm = Nothing
存儲過程取得的記錄集賦給MyRst,接下來,可以對MyRst進行操作。
在以上代碼中,CommandType屬性表明請求的類型,取值及說明如下:
-1 表明CommandText參數的類型無法確定
1 表明CommandText是一般的命令類型
2 表明CommandText參數是一個存在的表名稱
4 表明CommandText參數是一個存儲過程的名稱
還可以通過Connection對象或Recordset對象調用存儲過程,方法分別如下:
'**通過Connection對象調用存儲過程**
DIM MyConn,MyRst
Set MyConn = Server.CreateObject("ADODB.Connection")
MyConn.open MyConStr 'MyConStr是資料庫連接字串
Set MyRst = MyConn.Execute("getUserList",0,4) '最後一個參斷含義同CommandType
Set MyConn = Nothing
'**通過Recordset對象調用存儲過程**
DIM MyRst
Set MyRst = Server.CreateObject("ADODB.Recordset")
MyRst.open "getUserList",MyConStr,0,1,4
'MyConStr是資料庫連接字串,最後一個參斷含義與CommandType相同
2. 沒有輸入輸出的存儲過程
請看以下存儲過程:
/*SP2*/
CREATE PROCEDURE dbo.delUserAll
as
set nocount on
begin
delete from dbo.[userinfo]
end
go
該存儲過程刪去userinfo表中的所有記錄,沒有任何輸入及輸出,調用方法與上面講過的基本相同,只是不用取得記錄集:
'**通過Command對象調用存儲過程**
DIM MyComm
Set MyComm = Server.CreateObject("ADODB.Command")
MyComm.ActiveConnection = MyConStr 'MyConStr是資料庫連接字串
MyComm.CommandText = "delUserAll" '指定存儲過程名
MyComm.CommandType = 4 '表明這是一個存儲過程
MyComm.Prepared = true '要求將SQL命令先行編譯
MyComm.Execute '此處不必再取得記錄集
Set MyComm = Nothing
當然也可通過Connection對象或Recordset對象調用此類存儲過程,不過建立Recordset對象是為了取得記錄集,在沒有返回記錄集的情況下,還是利用Command對象吧。
3. 有返回值的存儲過程
在進行類似SP2的操作時,應充分利用SQL Server強大的事務處理功能,以維護數據的一致性。並且,我們可能需要存儲過程返回執行情況,為此,將SP2修改如下:
/*SP3*/
CREATE PROCEDURE dbo.delUserAll
as
set nocount on
begin
BEGIN TRANSACTION
delete from dbo.[userinfo]
IF @@error=0
begin
COMMIT TRANSACTION
⑼ 執行存儲過程顯示 游標不存在
將
close kecheng_cousor
deallocate kechang_cousor
移到循環外
create procere add_record @sno char(9)
as
declare @total_num int,@cno char(4)
SET NOCOUNT on;
select @total_num= COUNT(*) from Student where Sno=@sno
if @total_num=0
begin
print'該學生不存在!'
return
end
else
begin
declare kecheng_cursor CURSOR FOR select cno from course
open kecheng_cousor
fetch next from kecheng_cursor into @cno
while @@FETCH_STATUS=0
begin
select @total_num=COUNT(*) from SC where Sno=@sno and Cno=@cno
if @total_num>0
begin
FETCH NEXT FROM kecheng_cousor into @cno
continue
end
else
begin
insert into SC(Sno,cno,grade)values(@sno,@cno,100*RAND())
fetch next from kecheng_cousor into @cno
end
end
close kecheng_cousor
deallocate kechang_cousor
end
⑽ 資料庫中的存儲過程到底是什麼能不能舉個詳細的例子
存儲過程,實際就是一段寫在資料庫中的代碼。。
由於此段資料庫操作代碼由伺服器完成,而客戶端只是進行簡單的參數提交,所以,可以有效的利用伺服器的強勁而減小對客戶機的負合。
如:你想插入一條數據到資料庫。
雖然你的要求是,先檢查表裡面是否己存在該項。
如果不存在就Insert,如果存在就UPDATE。
這個時候,你就可以把這個判斷用存儲過程來寫。
你的程序只要提示你想要保存到資料庫裡面的東西即可。
下面就是一個簡單的存儲過程。
CREATE
PROCEDURE
[insert_A_Employees]
(@fWorkNo
[int],
@fWorkName
[char](10),
@fDeptName
[varchar](20),
@fGroupName
[varchar](20),
@fRecordDate
[datetime])
AS
declare
@iCount
int
select
@iCount
=
count(*)
from
A_EMPLOYEES
where
@fWorkNo
=
fWORKNO
--統計該工號在資料庫的數量賦值給
@iCount
if
@iCount
=
0
--如果資料庫中不存在該工號
begin
INSERT
INTO
[CLKQ].[dbo].[A_Employees]
--則插入數據
(
[fWorkNo],
[fWorkName],
[fDeptName],
[fGroupName],
[fRecordDate])
VALUES
(
@fWorkNo,
@fWorkName,
@fDeptName,
@fGroupName,
@fRecordDate)
return
1
--返回一個標識
end
else
begin
--否則則更新數據
update
[CLKQ].[dbo].[A_Employees]
set
[fWorkName]=@fWorkName,
[fDeptName]=@fDeptName,
[fGroupName]=@fGroupName,
[fRecordDate]=@fRecordDate
where
[fWorkNo]=@fWorkNo
return
0
--返回一個標識
end
GO
此時你只要在客戶端程序提供:
@fWorkNo
,
@fWorkName
,
@fDeptName
,
@fGroupName
,
@fRecordDate
這幾個值就行了。。
其它處理過程就由伺服器方處理了。
以上是以
SQL
資料庫為例。。。
ACCESS
等資料庫沒有此功能。