2016-03-03 154 views
0

這是MS SQL Server的:我已經包裹了系統存儲過程,sp_sequence_get_range,這樣我可以把它用一個簡單的選擇返回(我無法弄清楚如何處理與輸出參數在我的C#框架)。調用存儲過程與輸出參數

這是整個存儲過程:

CREATE PROCEDURE GetSequenceRange(@name VARCHAR, @counter INTEGER) AS 

DECLARE @firstValue SQL_VARIANT = 0; 
DECLARE @lastValue SQL_VARIANT = 0; 
DECLARE @sql NVARCHAR(MAX); 
SET @sql = N'EXEC sp_sequence_get_range @sequence_name = N''' + @name + N''', @range_size = ' + CONVERT(VARCHAR, @counter) 
    + N', @range_first_value = @firstValue OUTPUT, @range_last_value = @lastValue OUTPUT;' 
EXECUTE sp_executesql @sql, N'@name VARCHAR, @counter INTEGER, @firstValue SQL_VARIANT OUTPUT, @lastValue SQL_VARIANT OUTPUT', @name, @counter, @firstValue OUTPUT, @lastValue OUTPUT 
SELECT @firstValue, @lastValue 

當我嘗試執行像

exec GetSequenceRange 'tablename', 3 

的程序,我得到

無效的對象名稱 'T'。

不管我提供什麼名字,第一個字母都會在這個錯誤信息中返回。

我也曾嘗試

exec GetSequenceRange @name='tablename', @counter = 3 

在所有這些例子中的'tablename'是一個合格的序列名;我已經嘗試了owner.sequence和database.owner.sequence。

我覺得有一些根本性的錯誤我的做法,但我沒有看到它。

紅利,顯示如何從從C#調用sp_sequence_get_range的結果,而不必首先這個存儲過程包裝的答案。

+0

你試過方括號中的名字?例如[mydb]。[dbo]。[sometable] – BugFinder

+0

創建過程語句中缺少的varchar大小是問題所在。 –

+4

您還需要在動態sql中將長度添加到變量中。你應該總是聲明字符變量和列的長度。 –

回答

0

您應該能夠直接而方便地調用存儲過程。下面應該工作:

long _RangeFirstValue; 
long _RangeFirstValue; 

using (SqlConnection _Connection = new SqlConnection(_MyConnectionString)) 
{ 
    using (SqlCommand _Command = _Connection.CreateCommand()) 
    { 
     _Command.CommandText = "sp_sequence_get_range"; 
     _Command.CommandType = CommandType.StoredProcedure; 

     SqlParameter _ParamSequenceName = 
          new SqlParameter("sequence_name", SqlDbType.NVarChar, 776); 
     _ParamSequenceName.Value = _MySequenceName; 
     _Command.Parameters.Add(_ParamSequenceName); 

     SqlParameter _ParamRangeSize = new SqlParameter("range_size", SqlDbType.BigInt); 
     _ParamRangeSize.Value = _MyRangeSize; 
     _Command.Parameters.Add(_ParamRangeSize); 

     SqlParameter _ParamRangeFirstValue = 
          new SqlParameter("range_first_value", SqlDbType.Variant); 
     _ParamRangeFirstValue.Direction = ParameterDirection.Output; 
     _Command.Parameters.Add(_ParamRangeFirstValue); 

     SqlParameter _ParamRangeLastValue = 
          new SqlParameter("range_last_value", SqlDbType.Variant); 
     _ParamRangeLastValue.Direction = ParameterDirection.Output; 
     _Command.Parameters.Add(_ParamRangeLastValue); 

     _Command.ExecuteNonQuery(); 

     _RangeFirstValue = (long)(_ParamRangeFirstValue.Value); 
     _RangeLastValue = (long)(_ParamRangeLastValue.Value); 
    } 
} 
0

[編輯]

咩。張貼這個之後重讀這個問題,是的,這個問題可能太短 - varchars。賠率是sp_executeSQL可以在「未映射」的變量下正常運行。留下這個答案在這裏,因爲這個代碼應該簡化,如果只是爲了使未來的維護和修改更簡單。


首先,我完全同意,如果您可以直接調用系統程序,那麼你應該這麼做 - 動態SQL是一種痛苦,並且最好避免。隨着中說,隨着代碼的問題是,您的複雜動態SQL是困惑。

第一步是建立dynanmic SQL。這是很好,我現在有一些間距爲清楚起見在這裏將它複製:

SET @sql = N'EXEC sp_sequence_get_range @sequence_name = N''' 
+ @name 
+ N''', @range_size = ' 
+ CONVERT(VARCHAR, @counter) 
+ N', @range_first_value = @firstValue OUTPUT, @range_last_value = @lastValue OUTPUT;' 

在這裏,您正在使用的變量通過串聯硬編碼的文本@name和@counter。如果你在「MYNAME」和「42」過關,你(爲了清楚起見再次添加間距):

EXEC sp_sequence_get_range 
    @sequence_name  = N'MyName' 
,@range_size  = 42 
,@range_first_value = @firstValue OUTPUT 
,@range_last_value = @lastValue OUTPUT; 

然後,您可以通過這個作爲sp_executesql的第一個參數:

EXECUTE sp_executesql 
    @sql 
,N'@name VARCHAR, @counter INTEGER, @firstValue SQL_VARIANT OUTPUT, @lastValue SQL_VARIANT OUTPUT' 
,@name 
,@counter 
,@firstValue OUTPUT 
,@lastValue OUTPUT 

它就在那裏是 - 你試圖將@name和@counter作爲參數傳遞給sp_executeSQL,你不需要這樣做,因爲它們被硬編碼到動態SQL文本中。而且,它們沒有被定義爲@sql中的參數,以便sp_executeSQL將參數定義的值傳遞給(map?)。拿出來,它應該很好:

EXECUTE sp_executesql 
    @sql 
,N'@firstValue SQL_VARIANT OUTPUT, @lastValue SQL_VARIANT OUTPUT' 
,@firstValue OUTPUT 
,@lastValue OUTPUT