为什么我无法与比较结果进行比较?
Why can't I compare with the result of a comparison?
假设我有这样一个 table
:t1(c1, c2, ..., cn)
让我们进一步假设,如果 c2
等于 'v'
,我想 update
c1
到 1
,否则 0
。这就是我尝试的方式:
update t1
set c1 = (c2 = 'v');
我的目的是查看c2
是否等于'v'
并将逻辑值赋给c1
。根据 SSMS 2008,这有一个语法错误,所以我尝试了以下操作:
select c2 = 'v'
from t1;
它选择了所有行并显示 'v'
而不是 c2
的实际值。如您所见,我感到困惑,部分原因是 =
运算符的矛盾性,部分原因是它在 select
中的行为。当然,有效的问题已经解决了,但我想知道是否有一个清晰、合乎逻辑的解释来解释所描述的 =
操作员的行为。
答案很简单:
SQL 服务器中没有真正的布尔数据类型。有 BIT
,但这只是一个减少为 0
和 1
的整数值,您必须始终将其与您的目标值进行比较。
这行不通:
DECLARE @bit BIT=1;
IF @bit DoSomething;
你必须使用
IF @bit=1 DoSomething;
同CASE WHEN @bit=1 THEN ...
但实际上有一个布尔值,就像我们从 EXISTS
中知道的那样:
IF EXISTS(SELECT 1 FROM SomeWhere) DoSomething;
但这不是可以直接使用的数据类型...即使是 布尔值 标量函数,您也必须使用 RETURNS BIT
声明,并且您必须使用 return 值与 0 或 1 进行比较。
专长 1
这将不是return false而是将xyz填入@tst
DECLARE @tst VARCHAR(100)='test';
SELECT @tst='xyz';
SELECT @tst;
With paranthesis SQL服务器尝试取值,但是比较没有值...
SELECT (@tst='xyz'); --error
专长 2
这将使用左侧作为别名
SELECT test=Column FROM Table;
CASE 解决方案
这将只更新第二行
DECLARE @tbl TABLE(c1 int,c2 int, c3 int);
INSERT INTO @tbl VALUES(1,1,1),(2,2,3),(4,4,4);
UPDATE @tbl SET c1=CASE WHEN c2<>c3 THEN 99 ELSE c1 END
SELECT * FROM @tbl
更多示例:
这些是被禁止的
SET @bit=EXISTS(SELECT 1 FROM @tbl WHERE c1=50);
SET @bit=(EXISTS(SELECT 1 FROM @tbl WHERE c1=50));
SET @bit=(SELECT EXISTS(SELECT 1 FROM @tbl WHERE c1=50));
但这是允许的
SET @bit=CASE WHEN EXISTS(SELECT 1 FROM @tbl WHERE c1=50) THEN 1 ELSE 0 END;
有一个相关的问题,你可以进一步阅读:这个相关的问题也涵盖了这方面:Is there a Boolean data type in Microsoft SQL Server like there is in MySQL?
假设我有这样一个 table
:t1(c1, c2, ..., cn)
让我们进一步假设,如果 c2
等于 'v'
,我想 update
c1
到 1
,否则 0
。这就是我尝试的方式:
update t1
set c1 = (c2 = 'v');
我的目的是查看c2
是否等于'v'
并将逻辑值赋给c1
。根据 SSMS 2008,这有一个语法错误,所以我尝试了以下操作:
select c2 = 'v'
from t1;
它选择了所有行并显示 'v'
而不是 c2
的实际值。如您所见,我感到困惑,部分原因是 =
运算符的矛盾性,部分原因是它在 select
中的行为。当然,有效的问题已经解决了,但我想知道是否有一个清晰、合乎逻辑的解释来解释所描述的 =
操作员的行为。
答案很简单:
SQL 服务器中没有真正的布尔数据类型。有 BIT
,但这只是一个减少为 0
和 1
的整数值,您必须始终将其与您的目标值进行比较。
这行不通:
DECLARE @bit BIT=1;
IF @bit DoSomething;
你必须使用
IF @bit=1 DoSomething;
同CASE WHEN @bit=1 THEN ...
但实际上有一个布尔值,就像我们从 EXISTS
中知道的那样:
IF EXISTS(SELECT 1 FROM SomeWhere) DoSomething;
但这不是可以直接使用的数据类型...即使是 布尔值 标量函数,您也必须使用 RETURNS BIT
声明,并且您必须使用 return 值与 0 或 1 进行比较。
专长 1
这将不是return false而是将xyz填入@tst
DECLARE @tst VARCHAR(100)='test';
SELECT @tst='xyz';
SELECT @tst;
With paranthesis SQL服务器尝试取值,但是比较没有值...
SELECT (@tst='xyz'); --error
专长 2
这将使用左侧作为别名
SELECT test=Column FROM Table;
CASE 解决方案
这将只更新第二行
DECLARE @tbl TABLE(c1 int,c2 int, c3 int);
INSERT INTO @tbl VALUES(1,1,1),(2,2,3),(4,4,4);
UPDATE @tbl SET c1=CASE WHEN c2<>c3 THEN 99 ELSE c1 END
SELECT * FROM @tbl
更多示例:
这些是被禁止的
SET @bit=EXISTS(SELECT 1 FROM @tbl WHERE c1=50);
SET @bit=(EXISTS(SELECT 1 FROM @tbl WHERE c1=50));
SET @bit=(SELECT EXISTS(SELECT 1 FROM @tbl WHERE c1=50));
但这是允许的
SET @bit=CASE WHEN EXISTS(SELECT 1 FROM @tbl WHERE c1=50) THEN 1 ELSE 0 END;
有一个相关的问题,你可以进一步阅读:这个相关的问题也涵盖了这方面:Is there a Boolean data type in Microsoft SQL Server like there is in MySQL?