尝试重写存储过程,以便可以从 C# 传递 @tableName
Trying to rewrite a stored procedure so it is possible to pass on a @tableName from C#
我正在尝试将 table 名称传递给 SQL 服务器中的存储过程。
我知道默认情况下这是不可能的,因为 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
参数来工作-我此代码出现 2 个错误:
System.Data.SqlClient.SqlException: 'Must declare the scalar variable "@maxDateTime"
EXEC sp_executesql @FullQuery
显示错误:
Error: Procedure: [dbo].[getLastFeatureUpdate] has an unresolved reference to object [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 ;
我会说使用动态 table 名称表明您的 table 设计不佳,特别是当您将相似的数据拆分为多个 table 而不是单个 table 包含用于对数据进行分类的列。
我正在尝试将 table 名称传递给 SQL 服务器中的存储过程。
我知道默认情况下这是不可能的,因为 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
参数来工作-我此代码出现 2 个错误:
System.Data.SqlClient.SqlException: 'Must declare the scalar variable "@maxDateTime"
EXEC sp_executesql @FullQuery
显示错误:
Error: Procedure: [dbo].[getLastFeatureUpdate] has an unresolved reference to object [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 ;
我会说使用动态 table 名称表明您的 table 设计不佳,特别是当您将相似的数据拆分为多个 table 而不是单个 table 包含用于对数据进行分类的列。