当where子句中存在变量时,无法将nvarchar转换为int

时间:2015-07-15 04:23:25

标签: sql-server tsql where

select @now_total = COUNT(*) 
from CountTable 
where quotename(CHAR(65 + @i - 1)) > 0 ;

我在SQL Server中写了这个,以便获得列中的值的行数' A',B' ......' Z'大于0。但SQL Server告诉我

  

无法从nvarchar转换为int

我尝试将quotename更改为[A]>0,这没关系。但我必须计算i = 1 ... 26。对此有何正确的陈述?

谢谢!

2 个答案:

答案 0 :(得分:1)

您无法在SQL语句中间动态指定列名。

可以构造一个包含SQL语句的字符串,然后执行它:

declare @now_total int
declare @sql nvarchar(max)
set @sql = 
   'select @now_total = count(*) from CountTable where ' + quotename(char(64+@i)) + ' > 0;'
exec sp_executesql @sql, N'@now_total int output', @now_total output;

如您所见,这并不是很有趣。

最好从

更改表结构
create table CountTable (A int, B int, C int, ...)    
insert CountTable values (1, 34, 0, ..)

类似

create table CountTable (CountId int, ValueId char(1), Count int)
insert CountTable values (1, 'A', 1)
insert CountTable values (1, 'B', 34)
insert CountTable values (1, 'C', 0)
...

然后您的查询变为

select count(distinct CountId) from CountTable where ValueId=char(64+@i) and Count>0

您不必使用动态SQL。

答案 1 :(得分:1)

这是因为您无法使用纯SQL动态指定列。这里发生的是quotename(CHAR(65))转换为[A]。但是,不是使用列A,而是将其视为文字。因此,错误:

  

转换nvarchar值时转换失败' [A]'数据   输入int。

你应该使用动态sql:

CREATE TABLE tbl(
    ID INT IDENTITY(1, 1),
    A INT,
    B INT
)
INSERT INTO tbl(A, B) VALUES
(1, 1), (1, 2), (2, 2), (2, 3);

DECLARE @now_total INT
DECLARE @i INT = 1
DECLARE @sql NVARCHAR(MAX)

SET @sql = 'SELECT @now_total = COUNT(*) FROM tbl WHERE ' + QUOTENAME(CHAR(65 + @i - 1) ) + ' > 0'
EXEC sp_executesql @sql, N'@now_total INT OUT', @now_total OUT

SELECT @now_total

DROP TABLE tbl