在 sql server 中,使用整数变量构建动态 sql

Posted

技术标签:

【中文标题】在 sql server 中,使用整数变量构建动态 sql【英文标题】:In sql sever, building dynamic sql with integer variables 【发布时间】:2015-01-23 19:00:14 【问题描述】:

我正在构建这个动态 sql,但在执行时出错。

Conversion failed when converting the varchar value 'SELECT 
                    DDoSAttacksId,
                    AttackId,
                    TargetIP,
                    PeakBPS, 
                    DateStarted                                                                
            FROM (
                SELECT 
                    ROW_NUMBER() OVER (ORDER BY DateStarted Desc) AS Row,
                    DDoSAttacksId                                 AS DDoSAttacksId,
                    AttackId                                      AS AttackId,
                    TargetIP                                      As TargetIP,
                    CONCAT(PeakBPS / 1000000000,' Gbps')        As PeakBPS,
                    DateStarted                                   AS DateStarted
                FROM
                    DDosAttacks
                WHERE TargetIP IN ('108.61.51.101', '206.221.181.5')) AS DDosAttacksRows
            WHERE
                (Row between (' to data type int.

注意:它可以插入 IPAddress,但不能插入整数值。

set quoted_identifier off

declare @sql              nvarchar(4000),
        @PageNumber       int,
        @PageSize         int,
        @IPAddressList   varchar(100)

Select @IPAddressList = "'108.61.51.101', '206.221.181.5'"

select @sql= 'SELECT 
                DDoSAttacksId,
                AttackId,
                TargetIP,
                PeakBPS, 
                DateStarted                                                                
        FROM (
            SELECT 
                ROW_NUMBER() OVER (ORDER BY DateStarted Desc) AS Row,
                DDoSAttacksId                                 AS DDoSAttacksId,
                AttackId                                      AS AttackId,
                TargetIP                                      As TargetIP,
                CONCAT(PeakBPS / 1000000000,'' Gbps'')        As PeakBPS,
                DateStarted                                   AS DateStarted
            FROM
                DDosAttacks
            WHERE TargetIP IN ('+@IPAddressList+')) AS DDosAttacksRows
        WHERE
            (Row between ('+@PageNumber+' * ('+@PageSize+' - '+@PageSize+')) AND ('+@PageNumber+' * ('+@PageSize+' - 1)))';

EXECUTE sp_executesql @sql

我可以在它们的位置硬编码数字并执行良好....例如 (Row between (1 * (20 - 20)) AND (1 * (20 - 1)))';

【问题讨论】:

看来您正试图通过连接类型int(即(Row between (' + @PageNumber + 行中的@PageNumber)来构造一个无效的NVARCHAR 字符串。 How to Concatenate Numbers and Strings to Format Numbers in T-SQL?的可能重复 【参考方案1】:

你可以试试:

'(Row between ('+ cast(@PageNumber as varchar(255)) +' * ('+cast(@PageSizeas varchar(255)) +' - '+cast(@PageSize as varchar(255))+')) AND ('+cast(@PageNumber as varchar(255))+' * ('+cast(@PageSize as varchar(255))+' - 1)))';

由于下面的 KM 响应,更新了我的答案以提供转换后的 varchar 的长度。谢谢KM的解释。

【讨论】:

感谢它的工作......感谢所有做出类似回应的人......谢谢。 不指定 char/varchar 的长度是最糟糕的做法。当您的数据被截断时,您最终会被烧毁,因为默认值小于生成的字符串。 @KM 关于您的评论,当CAST 中省略长度时,系统不会将MAX 长度分配给VARCHAR @user3020047 为了帮助社区,您应该尽可能多地将答案标记为已接受。它有助于快速确定其他用户可能遇到的问题的解决方案。 @Anthony Forloney,没有 SQL Server 不会默认 varchar 为 max。当声明像DECLARE @x varchar 这样的变量时,它将默认为varchar(1)。当使用答案中的内联转换时,它将默认为varchar(30)。 SQL Server 无法读懂您的想法或了解您的需求,因此请始终选择适合您特定情况的数据类型和长度,您是程序员,请负责。见sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/…【参考方案2】:

+ 运算符在 SQL Server 中被重载。如果任何参数是数字,则默认为数字加号,而不是字符串连接。

解决方案是事先将值转换为字符串。比如:

cast(@PageNumber as varchar(255))

请注意,在使用 cast()convert() 时,您应该始终包含类型的长度。

【讨论】:

以上是关于在 sql server 中,使用整数变量构建动态 sql的主要内容,如果未能解决你的问题,请参考以下文章

将动态 SQL 的结果放入 sql-server 的变量中

在视图中包含变量的动态 SQL (SQL Server)

SQL Server 查询中的动态表名和变量名

sqlsever怎么定义两个整数变量,并分别赋值,最后输出两

如何在 SQL Server 的 OVER 子句中使用变量

当表名包含“'”时为 Sql Server 2008 构建动态查询