试图重写存储过程,以便可以从C#传递@tableName



我正试图将表名传递给SQL Server中的存储过程。

我已经理解,由于injection malicious attacks的风险,默认情况下不可能这样做。

当我在谷歌上搜索时,我明白了这无论如何都是可能的

无论如何,我都会尝试创建它,因为我已经明白,通过像下面这样声明string query是可能的。了解到风险,我无论如何都会尝试这样做,因为我真的很喜欢在过程中创建所有代码,使其更加干净。该代码也只能在我自己的电脑上使用。

存储过程的原始代码如下所示。我在这里把@tableName作为一个参数,然后就不起作用了,因为默认情况下不可能在这里传递tableName。

CREATE PROCEDURE getLastFeatureUpdate
@maxDateTime BIGINT = 0,
@tableName nvarchar
AS
SELECT
test.FeatureNbr,
test.DayTime,
test.Val
FROM
@tableName test 
WHERE
DayTime = (SELECT MAX(DayTime)
FROM @tableName
WHERE FeatureNbr = test.FeatureNbr 
AND DayTime <= @maxDateTime)

现在是这个版本,我正试图重写上面的代码,这样它就可以通过传递@tableName参数来工作了——我得到了这个代码的两个错误:

System.Data.SqlClient.SqlException:"必须声明标量变量"@maxDateTime";

EXEC sp_executesql @FullQuery显示错误:

错误:过程:[dbo]。[getLastFeatureUpdate]对对象[dbo]有一个未解析的引用。[sp_executesql]

然后我想知道我的代码中可能做错了什么?

重写存储过程:

CREATE PROCEDURE getLastFeatureUpdate
@maxDateTime BIGINT = 0,
@tableName nvarchar
AS
BEGIN
DECLARE @FullQuery nvarchar(1000)
SET @FullQuery = N'SELECT test.FeatureNbr, test.DayTime, test.Val FROM ' + QUOTENAME(@tableName) + ' test 
WHERE DayTime = ( SELECT MAX(DayTime) FROM ' + QUOTENAME(@tableName) + ' WHERE FeatureNbr = test.FeatureNbr AND DayTime <= @maxDateTime )'
EXEC sp_executesql @FullQuery
END

编辑:

执行存储过程的C#代码:

void getLastFeatureUpdate()
{
using (SqlConnection conn = new SqlConnection(GetConnectionString()))
{
conn.Open();
// 1.  create a command object identifying the stored procedure
SqlCommand cmd = new SqlCommand("getLastFeatureUpdate", conn);
// 2. set the command object so it knows to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add parameter to command, which will be passed to the stored procedure
cmd.Parameters.Add(new SqlParameter("@maxDateTime", 201010222045));
cmd.Parameters.Add(new SqlParameter("@tableName", "testTable"));
// execute the command
using (SqlDataReader rdr = cmd.ExecuteReader())
{
// iterate through results, printing each to console
while (rdr.Read())
{
Int64 v1 = (Int64)rdr["DayTime"];
int v2 = (Int16)rdr["FeatureNbr"];
double v3 = (double)rdr["Val"];
MessageBox.Show(v1 + "," + v2 + "," + v3);
}
}
}
}

当使用sp_executesql进行带参数的查询时,必须定义并传入参数:

EXECUTE sp_executesql 
@FullQuery, 
N'@maxDateTime float(53)',  
@maxDateTime ; 

我要说的是,使用动态表名表明您的表设计不好,特别是当您将类似的数据拆分为多个表,而不是一个带有列的表来对数据进行分类时。

最新更新