我试图创建一个计算列,以便在可空列上具有唯一索引,忽略NULL行 1 。我编写了这个测试用例:
SELECT TEST_ID, CODE, UNIQUE_CODE, CAST(UNIQUE_CODE AS VARBINARY(4000)) AS HEX
FROM (
SELECT TEST_ID, CODE,
ISNULL(CODE, CONVERT(VARCHAR, SPACE(10)) + CONVERT(VARCHAR, TEST_ID)) AS UNIQUE_CODE
FROM (
SELECT 1 AS TEST_ID, 'ABCDEFGHIJ' AS CODE
UNION ALL
SELECT 2, 'XYZ'
UNION ALL
SELECT 3, NULL
) TEST
) X;
当CODE
不为null时,它按预期工作,但当CODE
为空时,我只获得一个空格字符串(即,缺少尾随的TEST_ID
):
TEST_ID | CODE | UNIQUE_CODE | HEX
--------+------------+-------------+-----------------------
1 | ABCDEFGHIJ | ABCDEFGHIJ | 0x4142434445464748494A
2 | XYZ | XYZ | 0x58595A
3 | NULL | | 0x20202020202020202020
有趣的是,我已经在另一张桌子上成功使用了这项技术,但我无法发现差异:
CREATE TABLE SOME_OTHER_TABLE (
SOME_OTHER_TABLE_ID INT IDENTITY(1, 1) NOT NULL,
NOMBRE VARCHAR(50),
-- This works just fine:
NOMBRE_UNICO AS ISNULL(NOMBRE, CONVERT(VARCHAR, SPACE(50)) + CONVERT(VARCHAR, SOME_OTHER_TABLE_ID)),
CONSTRAINT SOME_OTHER_TABLE_PK PRIMARY KEY (SOME_OTHER_TABLE_ID)
);
我错过了什么?
( 1 )这是SQL Server 2005的一种解决方法,由于过滤了索引,在以后的版本中不再需要它。
答案 0 :(得分:3)
您可以使用" 3"
SELECT TEST_ID, CODE, UNIQUE_CODE, CAST(UNIQUE_CODE AS VARBINARY(4000)) AS HEX
FROM (
SELECT TEST_ID, CODE,
ISNULL(CODE, CONVERT(VARCHAR(20), SPACE(10)) + CONVERT(VARCHAR(20), TEST_ID)) AS UNIQUE_CODE
FROM (
SELECT 1 AS TEST_ID, cast('ABCDEFGHIJ' as varchar(20)) AS CODE
UNION ALL
SELECT 2, 'XYZ'
UNION ALL
SELECT 3, NULL
) TEST
) X;
'ABCDEFGHIJ'
(联合列表中的第一个值)正好是10个字符,此列是IsNull的第一个参数。因此,IsNull结果需要10个字符作为大小。这对于空间来说足够了。用'ABCDEFGHIJKLMNOPQR'
替换这个常量也可以解决问题。
答案 1 :(得分:1)
看起来SQL正试图帮助定义内部查询中的列长度。通过转换/转换为特定大小,这可以解决问题。在UNIQUE_CODE
字段超过此值后,返回的值将限制为列的大小。
SELECT TEST_ID, CODE, UNIQUE_CODE, CAST(UNIQUE_CODE AS VARBINARY(4000)) AS HEX
FROM (
SELECT TEST_ID, CODE,
ISNULL(CODE, CONVERT(VARCHAR, SPACE(10)) + CONVERT(VARCHAR, TEST_ID)) AS UNIQUE_CODE
FROM (
SELECT 1 AS TEST_ID, CONVERT(VARCHAR(50), 'ABCDEFGHIJ') AS CODE
UNION ALL
SELECT 2, 'XYZ'
UNION ALL
SELECT 3, NULL
) TEST
) X;
答案 2 :(得分:1)
你可以运行以下代码来找出原因吗?
这失败了:
declare @a char(20)
set @a=null
declare @b char(10)
set @b='aaaaaa'
select isnull(@a,convert(char(10),space(10)+@b))
这有效:
declare @a char(20)
set @a=null
declare @b char(10)
set @b='aaaaaa'
select isnull(@a,convert(char(30),space(10)+@b))