当 where 子句中有变量时,无法从 nvarchar 转换为 int

Cannot convert from nvarchar to int when there are variables in where clause

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

我在SQL服务器中写这个是为了得到列'A'、B'...'Z'中的值分别大于0的行数。但是 SQL 服务器告诉我

cannot convert from nvarchar to int

我尝试将 quotename 更改为 [A]>0,没关系。但我必须计算 i=1...26。正确的说法是什么?

谢谢!

您不能在这样的 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;

如您所见,这并不好玩。

最好将 table 结构从

更改为
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。

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

Conversion failed when converting the nvarchar value '[A]' to data type 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