我的程序有一个(稍微复杂一点)以下的版本:
CREATE PROC sp_Find_ID (
@Match1 varchar(10),
@Match2 varchar(10)
) AS
DECLARE @ID int
SELECT @ID = ID
FROM Table1
WHERE Match1 = @Match1
AND Coalesce(Match2,@Match2,'') = Coalesce(@Match2,Match2,'')
SELECT @ID ID
基本上Match1是强制匹配,但Match2在过程的输入和被搜索的表上都是可选的。第二个匹配成功,其中输入和/或表Match2值为null,或者它们都是相同(非空)值。
我的问题是:是否有更高效(甚至更可读)的方式?
我已经使用过这种方法几次,每次都感觉有点玷污(主观上是肮脏的)。
答案 0 :(得分:4)
是否有更高效(或更可读)的方式?
您使用COALESCE / etc提供的示例是non-sargable。您需要将事物分开,以便只运行查询中需要出现的内容:
DECLARE @ID int
IF @Match2 IS NOT NULL
BEGIN
SELECT @ID = t.id
FROM TABLE1 t
WHERE t.match1 = @Match1
AND (t.match2 = @Match2 OR t.match2 IS NULL)
END
ELSE
BEGIN
SELECT @ID = t.id
FROM TABLE1 t
WHERE t.match1 = @Match1
END
SELECT @ID ID
如果您希望在单个SQL语句中进行此操作,则动态SQL是唯一真正的替代方法。我强烈建议您在阅读之前阅读The curse and blessing of dynamic SQL:
DECLARE @SQL NVARCHAR(MAX)
SET @SQL = N' SELECT @ID = t.id
FROM TABLE1 t
WHERE t.match1 = @Match1 '
SET @SQL = @SQL + CASE
WHEN @Match2 IS NOT NULL THEN
' AND (t.match2 = @Match2 OR t.match2 IS NULL) '
ELSE
' '
END
BEGIN
EXEC sp_executesql @SQL,
N'@ID INT OUTPUT, @Match1 VARCHAR(10), @Match2 VARCHAR(10)',
@ID, @Match1, @Match2
END
答案 1 :(得分:4)
避免OR和ISNULL等
像这样的东西
DROP TABLE dbo.Table1
CREATE TABLE dbo.Table1 (ID int NOT NULL, Match1 int NOT NULL, Match2 int NULL)
INSERT dbo.Table1 VALUES (1, 55, 99), (2, 55, NULL)
DECLARE @Match1 int = 55, @Match2 int
SELECT ID
FROM
(
SELECT ID FROM Table1 WHERE Match1 = @Match1
EXCEPT -- @Match2 = NULL, match both rows (99, NULL)
SELECT ID FROM Table1 WHERE Match2 <> @Match2
) foo
SET @Match2 = -1
SELECT ID
FROM
(
SELECT ID FROM Table1 WHERE Match1 = @Match1
EXCEPT -- @Match2 = -1, match ID = 2 only where Match2 IS NULL
SELECT ID FROM Table1 WHERE Match2 <> @Match2
) foo
答案 2 :(得分:1)
不知道这是否更合适。
SELECT @ID = ID
FROM Table1
WHERE Match1 = @Match1
AND ((Match2 = @Match2) OR Coalesce(Match2,@Match2) IS NULL)
答案 3 :(得分:0)
对我来说似乎很简单?我一定错过了什么......你不需要Coalesce
SELECT @ID = ID
FROM Table1
WHERE Match1 = @Match1
AND (
(Match2 is null and @Match2 is null)
or
@Match2=Match2
)
SELECT @ID ID
答案 4 :(得分:0)
我认为应该这样做 - 假设@Match2
值为NULL
,如果它是可选的。
CREATE PROC sp_Find_ID (
@Match1 varchar(10),
@Match2 varchar(10)
) AS
DECLARE @ID int
SELECT @ID = ID
FROM Table1
WHERE Match1 = @Match1
AND Match2 = IsNull(@Match2, Match2)
SELECT @ID ID