調用存儲過程傳參
『壹』 如何給存儲過程,傳一個數組參數
方法一 分割
例:通過sql Server存儲過程傳送數組參數刪除多條記錄
eg. ID 值為'1,2,3' 以下存儲過程就是刪除表中id號為1,2,3的記錄:
CREATE PROCEDURE DeleteNews
@ID nvarchar(500)
as
DECLARE @PointerPrev int
DECLARE @PointerCurr int
DECLARE @TId int
Set @PointerPrev=1
while (@PointerPrev < LEN(@ID))
Begin
Set @PointerCurr=CharIndex(',',@ID,@PointerPrev)
if(@PointerCurr>0)
Begin
set @TId=cast(SUBSTRING(@ID,@PointerPrev,@PointerCurr-@PointerPrev) as int)
Delete from News whereID=@TID
SET @PointerPrev = @PointerCurr+1
End
else
Break
End
--刪除最後一個,因為最後一個後面沒有逗號,所以在循環中跳出,需另外再刪除
set @TId=cast(SUBSTRING(@ID,@PointerPrev,LEN(@ID)-@PointerPrev+1) as int)
Delete from News whereID=@TID
GO
這個方法麻煩不?於是又有另外一種方法——臨時表
方法二 Table對象
傳3個參數,都是數組形式還有時間類型用存儲過程更新
@Oid = 1,2,3,4
@Did = 111,222,333,444
@DateArr = '2007-1-1,2007-1-2,2007-1-3,2007-1-4'
CREATE proc Test999
@Oid nvarchar(1000)--ID1
,@Did nvarchar(1000)--ID2
,@DateArr nvarchar(1000)--日期
AS
DECLARE @id1s varchar(8000), @id2s varchar(8000), @dates varchar(8000)
set @id1s=@Oid
set @id2s=@Did
set @dates = @DateArr
-- 調用函數實現處理
SELECT @id1s=@id1s, @id2s=@id2s,@dates = @dates
UPDATE A SET terminate_time = B.dt
FROM [Table] A,(
SELECT
id1 = CONVERT(int, Desk_id.value),
id2 = CONVERT(int, room_id.value),
dt = CONVERT(datetime, terminate_time.value)
FROM dbo.f_splitstr(@id1s) Desk_id, dbo.f_splitstr(@id2s) room_id, dbo.f_splitstr(@dates) terminate_time
WHERE Desk_id.id = room_id.id
AND Desk_id.id = terminate_time.id
) B
WHERE A.Desk_id = B.ID1 AND A.room_id = B.ID2
GO這個還用到一個函數f_splitstr
CREATE FUNCTION dbo.f_splitstr(
@str varchar(8000)
)RETURNS @r TABLE(id int IDENTITY(1, 1), value varchar(5000))
AS
BEGIN
DECLARE @pos int
SET @pos = CHARINDEX(',', @str)
WHILE @pos > 0
BEGIN
INSERT @r(value) VALUES(LEFT(@str, @pos - 1))
SELECT
@str = STUFF(@str, 1, @pos, ''),
@pos = CHARINDEX(',', @str)
IF @str > ''
INSERT @r(value) VALUES(@str)
RETURN
這個方法更加可怕~~~輾轉網路,找到了一個還不錯的方法,用OPENXML,這個SQL2000就支持了。
方法三 xml
應該用SQL2000 OpenXML更簡單,效率更高,代碼更可讀:
CREATE Procere [dbo].[ProctListUpdateSpecialList]
(
@ProctId_Array NVARCHAR(2000),
@MoleId INT
)
AS
delete from ProctListSpecial whereMoleId=@MoleId
-- If empty, return
IF (@ProctId_Array IS NULL OR LEN(LTRIM(RTRIM(@ProctId_Array))) = 0)
RETURN
DECLARE @idoc int
EXEC sp_xml_preparedocument @idoc OUTPUT, @ProctId_Array
Insert into ProctListSpecial (MoleId,ProctId)
Select
@MoleId,C.[ProctId]
FROM
OPENXML(@idoc, '/Procts/Proct', 3)
with (ProctId int ) as C
where
C.[ProctId] is not null
EXEC sp_xml_removedocument @idoc
哇,看起來還是很復雜的說。有木有更好的辦法呢?
既然是OPENXML,為啥不用XML呢?於是查到,SQL2005以上都支持XML。Good,找到一片天了。
利用SQL2005的XML/XQuery功能,可以很方便的解決傳數組參數的問題。
declare @xml xml
set @xml = '<?xml version="1.0"?>
<ArrayOfInt>
<int>1</int>
<int>2</int>
<int>3</int>
</ArrayOfInt>'
select N.value( '(text())[1]','int' ) RoomId from @xml.nodes('/ArrayOfInt/int') V(N)
結果就是
註:上面的數據類型為XML
這樣就可以給存儲過程傳一個集合了,一般是數組,比如主鍵的集合。然後可用通過主鍵集合來查詢記錄。
客戶端可用使用序列化,把list轉化成xml。不過在序列化過程中,遇到了一些小麻煩。
1. .net默認是utf-16,SQL只認識utf-8
2. 出現很討厭的xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
可以用我這個類
public static class SerializeHelper
{
private static readonly XmlSerializerNamespaces Namespaces = new XmlSerializerNamespaces();
static SerializeHelper()
{
//去掉 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Namespaces.Add(string.Empty, string.Empty);
}
public static string SerializeXml<T>(T obj)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (MemoryStream stream = new MemoryStream())
{
serializer.Serialize(stream, obj, Namespaces);
return Encoding.UTF8.GetString(stream.ToArray());
}
}
public static T DeserializeXml<T>(string obj)
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
using (StringReader reader = new StringReader(obj))
{
return (T)serializer.Deserialize(reader);
}
}
}
SQL與XML,XQuery結合起來,功能會很強大的。
『貳』 存儲過程傳入參數
num1 NUMBER := 181,182;
這句話錯了啊!
DECLARE
num1 NUMBER ;
BEGIN
num1:=181; ----181,182 是什麼意思? 是要一下子傳兩個數字進去嗎? 這樣做不可以的哦?
Pr_d2_delCar(num1);
END;
『叄』 執行存儲過程怎麼傳入參數
在Oracle中定義存儲過程的時候有定義傳入參數的個數和類型的。
createprocerepro_name(v_para1invarchar2,v_para2invarchar2)
調用的時候:
declare
v_para1varchar2(30):='parameter1';
v_para2varchar2(30):='parameter2';
begin
pro_name(v_para1,v_para2);
end;
/
『肆』 Oracle調用存儲過程多個入參可以不全部傳參么
不行,就算沒有對應的參數,也要傳一個空值,不然會調用不到方法。
『伍』 oracle中調用存儲過程時傳遞參數值的3種方式。。
應該就是這三種吧。
1 , IN (參數值傳過來給存儲過程使用)
2, OUT(存儲過程返回結果給該參數)
3. IN OUT(存儲過程調用該參數的同時,最後還返回結果給調用的參數)