这是MS Sql Server:我已经包装了系统存储过程sp_sequence_get_range,这样我就可以通过一个简单的select返回它(我无法弄清楚如何在我的C#框架中处理OUTPUT参数)
这是整个存储过程:
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 :(得分: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);
}
}
答案 1 :(得分:0)
[编辑]
咩。在发布此问题后重新阅读问题,是的,问题可能是太短的varchars。赔率是sp_executeSQL将与“未映射”变量一起正常运行。在这里留下这个答案,因为这个代码应该简化,如果只是为了使将来的维护和修改更简单。
首先,我完全同意如果您可以直接调用系统过程,那么您应该这样做 - 动态SQL很痛苦,最好避免。话虽如此,此代码的问题在于您的复杂动态SQL会混淆。
第一步是构建动态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将参数定义的值传递(映射?)到。拿出来,它应该没问题:
EXECUTE sp_executesql
@sql
,N'@firstValue SQL_VARIANT OUTPUT, @lastValue SQL_VARIANT OUTPUT'
,@firstValue OUTPUT
,@lastValue OUTPUT