在简化版中我试图做类似的事情:
Set @datepart = 'DATEPART(year, myDate)'
Set @SQLQuery = 'SELECT @datepart AS TIME
FROM someTable
GROUP BY @datepart'
Execute sp_executesql @SQLQuery, N'@datepart nvarchar(1000)', @datepart
但我明白了:
每个GROUP BY表达式必须包含至少一个不是的列 外部参考。
如果我没有参数化它就可以工作,意味着
Set @SQLQuery = 'SELECT ' + @datepart + ' AS TIME
FROM someTable
GROUP BY ' + @datepart
Execute sp_executesql @SQLQuery
答案 0 :(得分:3)
通过使用参数化查询,您无法实现您想要做的只是简单的动态查询
Set @SQLQuery = 'SELECT ' + @datepart + ' AS TIME
FROM someTable
GROUP BY ' + @datepart
Execute sp_executesql @SQLQuery
因为变量只是作为动态查询中的值。请考虑以下示例。
DECLARE @datepart NVARCHAR(1000),
@SQLQuery NVARCHAR(max)
SET @datepart = 'DATEPART(year, getdate())'
SET @SQLQuery = 'SELECT @datepart AS TIME'
EXECUTE Sp_executesql
@SQLQuery,
N'@datepart nvarchar(1000)',
@datepart
根据你的答案,答案应该是2015
,但结果是
DATEPART(year, getdate())
答案 1 :(得分:2)
其他人没有意识到的是你提出了一个问题并自己解决了。 SQL Server已经非常正确地指出您正在尝试分组某些内容,但报告没有输出。
我接受了你的查询并制作了一个版本,几乎我们所有人都应该可以在SQL 2005 +上使用:
DECLARE @datepart NVARCHAR(MAX), @SQLQUERY NVARCHAR(MAX)
SEt @datepart = 'DATEPART(year, myDate)'
Set @SQLQuery = 'SELECT @datepart AS TIME
FROM sys.objects
GROUP BY @datepart'
Execute sp_executesql @SQLQuery, N'@datepart nvarchar(1000)', @datepart
现在,这将按预期爆炸。原因是@datepart是字符串值。它实际上是试图:
SELECT'String'FROM'Table'GROUP BY'Btring'
它实际上不需要表格来回答这个问题。 SQL混乱地抛出它的手臂。你需要做些什么才能实现看起来要做的事情,只需将字符串连接在一起,但不建议这可能是:
DECLARE @datepart NVARCHAR(MAX), @SQLQUERY NVARCHAR(MAX)
SEt @datepart = 'DATEPART(year, create_date)'
Set @SQLQuery = 'SELECT ' + @datepart +' AS TIME
FROM sys.objects
GROUP BY '+ @datepart
Execute sp_executesql @SQLQuery
或者在您的具体案例中:
DECLARE @datepart NVARCHAR(MAX), @SQLQUERY NVARCHAR(MAX)
SEt @datepart = 'DATEPART(year, myDate)'
Set @SQLQuery = 'SELECT ' + @datepart +' AS TIME
FROM someTable
GROUP BY '+ @datepart
Execute sp_executesql @SQLQuery
如果您提交这样的代码,我建议您输入简历。这是不好的做法。
答案 2 :(得分:0)
我认为简单的选择应该做这个工作。 查询是
SELECT DISTINCT DATEPART(year,mydate) AS TIME
FROM someTable
对于动态查询:
Set @SQLQuery = 'SELECT DISTINCT' + @datepart + ' AS TIME
FROM someTable'
Execute sp_executesql @SQLQuery
答案 3 :(得分:0)
如果您在运行时使用变量REPLACE
查询,则可以实现2015
动态
DECLARE @datepart NVARCHAR(100),
@SQLQuery NVARCHAR(max)
SET @datepart = 'DATEPART(year, getdate())'
SET @SQLQuery = 'SELECT @datepart AS TIME'
SET @SQLQuery = REPLACE(@SQLQuery, '@datepart', @datepart)
exec (@SQLQuery);
答案 4 :(得分:0)
@tinka,这很好用。但我只是测试了另一个例子,它似乎没有帮助反对SQLinjection。也许你的解决方案与使用普通的连接查询相同?
DECLARE @SQLQueryInnen nvarchar(max)
DECLARE @ParameterDefinition nvarchar(max)
DECLARE @aufnr nvarchar(200)
SET @aufnr = '1234; SELECT * FROM sensitiveTable'-- here the attacker inserted an SQL Statement in aufnr
Set @SQLQueryInnen = 'SELECT * FROM myTable WHERE aufnr = @aufnr'
Set @SQLQueryInnen = REPLACE(@SQLQueryInnen, '@aufnr', @aufnr)
Set @ParameterDefinition = '@aufnr nvarchar(200)'
Execute sp_Executesql @SQLQueryInnen, @ParameterDefinition, @aufnr
-- Result: The illegal SELECT statement gets executed!!!
如果我在没有REPLACE的情况下执行此示例,则攻击无法正常工作但您得到:Conversion failed when converting the nvarchar value '1234; SELECT * FROM qdb_tab_imp_me_q_fehler' to data type int.