T-SQL ISNULL() 保留字 'Primary' 的错误行为(SQL Server 2014)
T-SQL ISNULL() incorrect behaviour with reserved word 'Primary' (SQL Server 2014)
前几天我遇到了这个问题,它不是一个专业,因为我可以解决它,但想知道是否有人可以提供任何见解,或者我是否发现了一个模糊的错误?
我们有一个旧数据库 table,它有一个名为 Primary 的列,这显然是一个保留字。当 运行 一个 T-SQL 查询时,我遇到了一些奇怪的结果,这似乎表明 ISNULL 函数正在将列名视为保留字。仅仅是因为周五晚了,我在这里遗漏了一些非常明显的东西,还是这里发生了什么奇怪的事情?
这里有一些简单的 SQL 设置几个测试 table 来说明它。
CREATE TABLE [dbo].[Customer]
(
[CustomerID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Customer]
PRIMARY KEY CLUSTERED ([CustomerID] ASC)
) ON [PRIMARY]
CREATE TABLE [dbo].[OrderTaken]
(
[OrderID] [int] IDENTITY(1,1) NOT NULL,
[Description] [varchar](50) NOT NULL,
[CustomerID] [int] NOT NULL,
[Primary] [bit] NOT NULL,
CONSTRAINT [PK_Order]
PRIMARY KEY CLUSTERED ([OrderID] ASC)
) ON [PRIMARY]
ALTER TABLE [dbo].[OrderTaken] WITH CHECK
ADD CONSTRAINT [FK_Order_Customer]
FOREIGN KEY([CustomerID]) REFERENCES [dbo].[Customer] ([CustomerID])
GO
ALTER TABLE [dbo].[OrderTaken] CHECK CONSTRAINT [FK_Order_Customer]
GO
INSERT INTO [dbo].[Customer](Name) VALUES('Bob')
INSERT INTO [dbo].[Customer](Name) VALUES('Dave')
INSERT INTO [dbo].[Customer](Name) VALUES('Fred')
INSERT INTO [dbo].[Customer](Name) VALUES('Paul')
GO
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES ('Order1', 1, 1)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order2', 2, 1)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order3', 2, 1)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order4', 3, 0)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order5', 3, 0)
Go
这是查询
SELECT
C.CustomerID, C.Name,
O.OrderID, ISNULL(O.[OrderID], -1),
O.[Primary], ISNULL(O.[Primary], -1) as Weird
FROM
Customer C
LEFT JOIN
OrderTaken O ON C.CustomerID = O.CustomerID
请注意,对于没有订单的客户行,O.Primary 是 NULL ,但 ISNULL(O.[Primary],-1) returns 1 而不是 -1
问题不在于字段名称,而在于字段类型 - bit
。
它不能保存 -1
值,只能保存 0
和 1
。当 SQL 服务器尝试将值更改为 -1
时,它会检查 -1 <> 0
并设置 1
(true
)。参见 documentation。
所以检查前转换字段:
SELECT
C.CustomerID,
C.Name,
O.OrderID,
ISNULL(O.[OrderID],-1),
O.[Primary],
ISNULL(CONVERT(int,O.[Primary]),-1) as Weird
FROM Customer C
LEFT JOIN OrderTaken O
ON C.CustomerID = O.CustomerID
或将列类型更改为 int
或 tinyint
。
前几天我遇到了这个问题,它不是一个专业,因为我可以解决它,但想知道是否有人可以提供任何见解,或者我是否发现了一个模糊的错误?
我们有一个旧数据库 table,它有一个名为 Primary 的列,这显然是一个保留字。当 运行 一个 T-SQL 查询时,我遇到了一些奇怪的结果,这似乎表明 ISNULL 函数正在将列名视为保留字。仅仅是因为周五晚了,我在这里遗漏了一些非常明显的东西,还是这里发生了什么奇怪的事情?
这里有一些简单的 SQL 设置几个测试 table 来说明它。
CREATE TABLE [dbo].[Customer]
(
[CustomerID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Customer]
PRIMARY KEY CLUSTERED ([CustomerID] ASC)
) ON [PRIMARY]
CREATE TABLE [dbo].[OrderTaken]
(
[OrderID] [int] IDENTITY(1,1) NOT NULL,
[Description] [varchar](50) NOT NULL,
[CustomerID] [int] NOT NULL,
[Primary] [bit] NOT NULL,
CONSTRAINT [PK_Order]
PRIMARY KEY CLUSTERED ([OrderID] ASC)
) ON [PRIMARY]
ALTER TABLE [dbo].[OrderTaken] WITH CHECK
ADD CONSTRAINT [FK_Order_Customer]
FOREIGN KEY([CustomerID]) REFERENCES [dbo].[Customer] ([CustomerID])
GO
ALTER TABLE [dbo].[OrderTaken] CHECK CONSTRAINT [FK_Order_Customer]
GO
INSERT INTO [dbo].[Customer](Name) VALUES('Bob')
INSERT INTO [dbo].[Customer](Name) VALUES('Dave')
INSERT INTO [dbo].[Customer](Name) VALUES('Fred')
INSERT INTO [dbo].[Customer](Name) VALUES('Paul')
GO
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES ('Order1', 1, 1)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order2', 2, 1)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order3', 2, 1)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order4', 3, 0)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order5', 3, 0)
Go
这是查询
SELECT
C.CustomerID, C.Name,
O.OrderID, ISNULL(O.[OrderID], -1),
O.[Primary], ISNULL(O.[Primary], -1) as Weird
FROM
Customer C
LEFT JOIN
OrderTaken O ON C.CustomerID = O.CustomerID
请注意,对于没有订单的客户行,O.Primary 是 NULL ,但 ISNULL(O.[Primary],-1) returns 1 而不是 -1
问题不在于字段名称,而在于字段类型 - bit
。
它不能保存 -1
值,只能保存 0
和 1
。当 SQL 服务器尝试将值更改为 -1
时,它会检查 -1 <> 0
并设置 1
(true
)。参见 documentation。
所以检查前转换字段:
SELECT
C.CustomerID,
C.Name,
O.OrderID,
ISNULL(O.[OrderID],-1),
O.[Primary],
ISNULL(CONVERT(int,O.[Primary]),-1) as Weird
FROM Customer C
LEFT JOIN OrderTaken O
ON C.CustomerID = O.CustomerID
或将列类型更改为 int
或 tinyint
。