存储过程中的Sql变量表名错误

时间:2017-06-19 06:17:01

标签: sql-server stored-procedures

我想创建程序,我收到以下错误;

  

转换nvarchar值时转换失败'选择ID为#a   来自@table,其中yil ='数据类型int。

如何写出正确的程序?我的程序;

@tablo nvarchar(100),
@kayit nvarchar(50),
@inceleme nvarchar(50),
@icevap nvarchar(50),
@tespit nvarchar(MAX),
@scevap nvarchar(MAX),
@aksiyon nvarchar(50),
@mutalaa nvarchar(MAX),
@tamamlanma nvarchar(100),
@not nvarchar(MAX),
@izleme nvarchar(50),
@kaydeden nvarchar(50),
@idd int,
@kullanici nvarchar(50),
 @yil int,
@donem int

as

DECLARE @sql as varchar(max)
SET @sql = 'select ID into #a from' + @tablo+
' Where yil='+@yil+' and donem='+@donem+' and (ilkkaydeden is 
null or ilkkaydeden='') and (kull='+@kullanici+' or 
kull1='+@kullanici+' or kull2='+@kullanici+')'
EXEC(@sql)

4 个答案:

答案 0 :(得分:0)

你有两个变量为整数@yil& @donem并且您无法在未将其转换为varcharnvarchar的情况下将它们连接起来。

使用下一个代码: -

DECLARE @sql as varchar(max)
SET @sql = 'select ID into #a from' + @tablo+
' Where yil='+convert(nvarchar(20),@yil)+' and donem='+convert(nvarchar(20),@donem)+' and (ilkkaydeden is 
null or ilkkaydeden='') and (kull='+@kullanici+' or 
kull1='+@kullanici+' or kull2='+@kullanici+')'
EXEC(@sql)

答案 1 :(得分:0)

对于INT值,声明为INT,然后在创建动态sql时,使用

  CONVERT(VARCHAR, @var)

对于char值,请添加如下所示的额外引号:

 '...var='''+@char_var+''' more text..'

答案 2 :(得分:0)

您不应该像现在一样编写存储过程,它们容易受到SQL注入攻击。使用参数化查询重写它们,它们是安全的:

CREATE PROCEDURE test
    @tablo NVARCHAR(100)
  , @kayit NVARCHAR(50)
  , @inceleme NVARCHAR(50)
  , @icevap NVARCHAR(50)
  , @tespit NVARCHAR(MAX)
  , @scevap NVARCHAR(MAX)
  , @aksiyon NVARCHAR(50)
  , @mutalaa NVARCHAR(MAX)
  , @tamamlanma NVARCHAR(100)
  , @not NVARCHAR(MAX)
  , @izleme NVARCHAR(50)
  , @kaydeden NVARCHAR(50)
  , @idd INT
  , @kullanici NVARCHAR(50)
  , @yil INT
  , @donem INT
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @sql NVARCHAR(MAX);

    SET @tablo = (   SELECT FORMATMESSAGE('%s.%s', QUOTENAME(SCHEMA_NAME(O.schema_id)), QUOTENAME(O.name))
                     FROM sys.objects AS O
                     WHERE O.object_id = OBJECT_ID(@tablo, 'U'));

    SET @sql = N'
        SELECT ID
        INTO #a
        FROM ' + @tablo + '
        WHERE yil = @yil
        AND donem = @donem
        AND (ilkkaydeden IS NULL OR ilkkaydeden = '')
        AND @kullanici IN (kull, kull1, kull2);';

    EXEC sys.sp_executesql @sql, N'@yil INT, @donem INT, @kullanici NVARCHAR(50)', @yil, @donem, @kullanici;
END;

如果必须动态插入表名,将其包装到QUOTENAME()函数中,它会将变量包装成方括号并使其成为有效的对象名。

在这种情况下,我甚至会检查@tablo表是否存在并为其分配一个正确的值,这是一个模式和表的混合,可以安全使用。

答案 3 :(得分:-2)

更新(评论后):然后将 int 变量转换为 varchar ,以便连接工作

DECLARE @tablo NVARCHAR(100)
    , @kayit NVARCHAR(50)
    , @inceleme NVARCHAR(50)
    , @icevap NVARCHAR(50)
    , @tespit NVARCHAR(MAX)
    , @scevap NVARCHAR(MAX)
    , @aksiyon NVARCHAR(50)
    , @mutalaa NVARCHAR(MAX)
    , @tamamlanma NVARCHAR(100)
    , @not NVARCHAR(MAX)
    , @izleme NVARCHAR(50)
    , @kaydeden NVARCHAR(50)
    , @idd INT
    , @kullanici NVARCHAR(50)
    , @yil INT
    , @donem INT
DECLARE @sql AS VARCHAR(max)

SET @sql = 'select ID into #a from' + @tablo + ' Where yil=' + cast(@yil as varchar) + ' and donem=' +  cast(@donem as varchar) + ' and (ilkkaydeden is 
null or ilkkaydeden='') and (kull=' + @kullanici + ' or 
kull1=' + @kullanici + ' or kull2=' + @kullanici + ')'

EXEC (@sql)