C# 为什么SQL Server存储过程中的输出参数总是返回null?
我编写了一个C程序,它调用SQL Server存储过程从数据库中获取信息 C程序:C# 为什么SQL Server存储过程中的输出参数总是返回null?,c#,sql-server,stored-procedures,C#,Sql Server,Stored Procedures,我编写了一个C程序,它调用SQL Server存储过程从数据库中获取信息 C程序: public void testing(ref int pIMPORT_ID) { string sMessage = null; int sValue = 0; ADODB.Command cnnCmd = null; object resc; ModCommon.adodb_connect(); cnnCmd = new ADODB.Command();
public void testing(ref int pIMPORT_ID)
{
string sMessage = null;
int sValue = 0;
ADODB.Command cnnCmd = null;
object resc;
ModCommon.adodb_connect();
cnnCmd = new ADODB.Command();
cnnCmd.ActiveConnection = ModMain.gConn;
cnnCmd.CommandType = ADODB.CommandTypeEnum.adCmdStoredProc;
cnnCmd.CommandText = "sp_TEST";
try
{
cnnCmd.Parameters.Append(cnnCmd.CreateParameter("RETURN_VALUE", ADODB.DataTypeEnum.adInteger, ADODB.ParameterDirectionEnum.adParamReturnValue));
cnnCmd.Parameters.Append(cnnCmd.CreateParameter("IMPORT_ID", ADODB.DataTypeEnum.adInteger, ADODB.ParameterDirectionEnum.adParamInput));
cnnCmd.Parameters.Append(cnnCmd.CreateParameter("MSG", ADODB.DataTypeEnum.adVarChar, ADODB.ParameterDirectionEnum.adParamOutput, 200));
cnnCmd.Parameters.Refresh();
cnnCmd.Parameters["@IMPORT_ID"].Value = pIMPORT_ID;
cnnCmd.Execute(out resc);
sMessage = cnnCmd.Parameters["@MSG"].Value;
sValue = cnnCmd.Parameters["@RETURN_VALUE"].Value;
ModMain.gConn.Close();
}
catch (Exception ex)
{
FileSystem.FileOpen(11, ModMain.strErrLogFile, OpenMode.Output);
FileSystem.PrintLine(11, "*****");
FileSystem.PrintLine(11, "Error occurs!");
FileSystem.FileClose(11);
System.Environment.Exit(0);
}
}
在执行以下存储过程之后,我为sMessage获取{},为sValue获取null
但是在执行以下存储过程之后,与上面相同,但是使用execute@SQL注释后,对于sMessage,我得到的不是空的,对于sValue,我得到的是0,这是期望的结果
ALTER PROCEDURE [dbo].[sp_TEST_TEMP_TABLE]
@IMPORT_ID int,
@MSG varchar(200) output
AS
BEGIN
DECLARE @SQL varchar(4000)
DECLARE @cnt_B int = 0
CREATE TABLE #TEMP(cnt int)
SELECT @SQL = 'insert into #TEMP select count(*) from STAFF where IMPORT_ID = ' + STR(@IMPORT_ID)
--exec (@SQL)
IF @@ROWCOUNT > 0
SET @MSG = 'NOT EMPTY'
ELSE
SET @MSG = 'EMPTY'
DROP TABLE #TEMP
RETURN 0
END
GO
为什么会这样?STAFF表不是空的。在SSMS中执行存储过程并查找任何错误。对我来说,这是: Msg 208,16级,状态1,第1行 无效的对象名称“STAFF” 动态SQL获取的数据库上下文完全可能与存储过程所在的数据库上下文不同。因此,按照流行程度的顺序: 确保您确实需要使用动态SQL。是的,每次您进入这个领域时都必须证明它是正确的,因为它使您的代码可能容易受到注入攻击。 使用数据库上下文开关预先编写动态语句。例如: set@SQL='use'+quotenamedb_name+'; 将导入ID='+STR@IMPORT_ID; 参数化动态语句。这将需要舍弃exec以支持sys.sp_executesql,但下次尝试连接来自用户的字符串参数时,您会很高兴这样做 确保您动态触摸的任何对象都存在于当前数据库中,否则您将得到错误208,并且它具有相应的列错误207。
在SSMS中执行存储过程并查找任何错误。对我来说,这是: Msg 208,16级,状态1,第1行 无效的对象名称“STAFF” 动态SQL获取的数据库上下文完全可能与存储过程所在的数据库上下文不同。因此,按照流行程度的顺序: 确保您确实需要使用动态SQL。是的,每次您进入这个领域时都必须证明它是正确的,因为它使您的代码可能容易受到注入攻击。 使用数据库上下文开关预先编写动态语句。例如: set@SQL='use'+quotenamedb_name+'; 将导入ID='+STR@IMPORT_ID; 参数化动态语句。这将需要舍弃exec以支持sys.sp_executesql,但下次尝试连接来自用户的字符串参数时,您会很高兴这样做 确保您动态触摸的任何对象都存在于当前数据库中,否则您将得到错误208,并且它具有相应的列错误207。
我认为您不应该在本例中使用@ROWCOUNT,为什么不查询临时表以查看是否有行 我也不确定我是否理解您为什么要编写动态查询 您可以这样做:
DECLARE @cnt as int
SELECT @cnt = count(*) from STAFF where IMPORT_ID = @IMPORT_ID
if (@cnt > 0) etc...
我认为您不应该在本例中使用@ROWCOUNT,为什么不查询临时表以查看是否有行 我也不确定我是否理解您为什么要编写动态查询 您可以这样做:
DECLARE @cnt as int
SELECT @cnt = count(*) from STAFF where IMPORT_ID = @IMPORT_ID
if (@cnt > 0) etc...
旁注:存储过程不应使用sp_uu前缀。微软已经这样做了,而且你确实有可能在将来的某个时候发生名称冲突。最好只是简单地避免使用sp_u,并使用其他东西作为前缀——或者根本不使用前缀!旁注:存储过程不应使用sp_uu前缀。微软已经这样做了,而且你确实有可能在将来的某个时候发生名称冲突。最好只是简单地避免使用sp_u,并使用其他东西作为前缀——或者根本不使用前缀!