我有以下存储过程
CREATE PROCEDURE [dbo].[Insert]
@Service varchar(max),
@TableName varchar(100),
@Query varchar(250),
@Results varchar(max),
@CreatedDate datetime,
@ExpirationDate datetime
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
DECLARE @SQL NVARCHAR(MAX), @ParmDefinition NVARCHAR(MAX)
DECLARE @q1 VARCHAR(MAX), @rez1 VARCHAR(MAX),
@date1 DATETIME, @date2 DATETIME
DECLARE @tablename VARCHAR(MAX) = @Service + '.' + @TableName
SET @SQL = N'if not EXISTS (select @q from ' + @tablename + ' where Query = @q) insert into ' + @tablename + ' values(@q, @rez, @date1, @date2)'
SET @ParmDefinition = N'@q varchar(max), @rez varchar(max),
@date1 datetime, @date2 datetime'
EXECUTE sp_executeSQL -- Dynamic T-SQL
@SQL,
@ParmDefinition,
@q = @Query,
@rez = @Results,
@date1= @CreatedDate,
@date2 = @ExpirationDate
COMMIT TRANSACTION
END
当我尝试执行它时,它不会插入任何内容,0行
如果我在没有存储过程的情况下执行代码,就像单个查询一样,它会插入
我错过了什么吗?
答案 0 :(得分:3)
你的问题中有很多事情对我没有任何意义,为什么你需要在你的程序中声明所有这些变量。
是的,你是使用参数化查询来保护自己免受sql注入攻击,但你通过连接对象名称(表和数据库名称)留下了一个漏洞,是的你需要连接它们但你可以使用{{1}它们周围的函数传递参数并强制执行sql server以在这些参数周围加上方括号,并强制sql server将它们视为对象名称。
选择QUOTENAME()
中的变量没有多大意义。选择1,如果找到具有匹配条件的行,则返回true;如果未找到任何行,则只会插入一行。
只声明需要声明的变量,否则会使它看起来像一团糟,难以调试。正如他们所说IF EXISTS
:)
同样为参数使用适当的数据类型Keep it simple
我相信你的数据库名称为什么它需要是VARCHAR(MAX)数据类型,使用特定的数据类型来存储Sql Server对象名@Service
1}}。
SYSNAME