您的日期文字需要在單引號括起來(我用CHAR(39)通常是因爲它更容易閱讀並且不需要轉義)。否則,你說:
WHERE birth_date = (12) - (12) - (2000)
解析爲:
WHERE birth_date = -2000
解析爲DATEADD(DAY, -2000, '1900-01-01')
或:
WHERE birth_date = '1894-07-11'
這可能不會得到你想要的結果。
隨着典型的SQL注入警告取代當然,並假設@columnName
始終是一個字符串或日期/時間列,這裏是我將如何重新編寫您的存儲過程(儘管我可能會嘗試避免動態SQL如果我可以的話)。
ALTER PROCEDURE dbo.aaa
@columnName NVARCHAR(10),
@comparisonParam NVARCHAR(10),
@val NVARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'SELECT * FROM dbo.Sheep WHERE '
+ QUOTENAME(@columnName) + @comparisonParam + CHAR(39)
+ REPLACE(@val, CHAR(39), CHAR(39) + CHAR(39))
+ CHAR(39);
EXEC sp_executesql @sql;
END
GO
爲了防止潛在問題,您可能需要爲列和數據類型添加驗證,並確保操作符合您的預期。例如
CREATE PROCEDURE dbo.bbb
@columnName NVARCHAR(10),
@comparisonParam NVARCHAR(10),
@val NVARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @delimiter CHAR(1);
SELECT @delimiter = CASE
WHEN [system_type_id] IN
(104,48,52,56,127,59,60,62,106,108,122) THEN '' -- numeric
WHEN [system_type_id] IN
(35,40,41,42,43,58,61,99,167,175,231,239) THEN CHAR(39) -- string
END FROM sys.columns WHERE [object_id] = OBJECT_ID(N'dbo.Sheep')
AND name = @columnName;
IF @delimiter IS NULL
BEGIN
RAISERROR('Column ''%s'' was not found or an unexpected data type.', 11, 1,
@columnName);
RETURN;
END
IF @comparisonParam NOT IN (N'=', N'>=', N'<=', N'<', N'>', N'LIKE')
BEGIN
RAISERROR('Comparison param ''%s'' was not valid.', 11, 1, @comparisonParam);
RETURN;
END
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'SELECT * FROM dbo.Sheep WHERE '
+ QUOTENAME(@columnName) + ' ' + @comparisonParam + ' '
+ @delimiter + REPLACE(@val, CHAR(39), CHAR(39) + CHAR(39))
+ @delimiter;
EXEC sp_executesql @sql;
END
GO
現在確保您爲字符串文字使用明確的日期格式。 12-12-2000
不是一個好的選擇。 20001212
好得多。
有可能有一些方法來做到這一點沒有動態SQL - 我給了very simplified answer here。根據數據類型,潛在列的數量以及要支持的操作數量,這可能是可行的。
是否使用C#,vb.net? – 2012-07-14 09:45:12