用 CASE WHEN NOT EXISTS 设置参数值总是出来 0
Set parameter value with CASE WHEN NOT EXISTS always comes out to 0
我有一个参数 (@noMatch int output
),我根据在下面的存储过程中找到的 CASE
为其赋值:
ALTER PROCEDURE [dbo].[p_trips_non_aggregate_insert]
@trips u_trips_non_aggregate readonly,
@rowCount int OUTPUT,
@noMatch int OUTPUT
WITH RECOMPILE
AS
BEGIN TRANSACTION
SET NOCOUNT ON
INSERT INTO [dbo].[trips_non_aggregate]
([LøyvehaverID], [KjøretøyID], [Ordrenummer], [c], [År], [Måned], [Betaling (brutto)], [Betaling (netto)], [LøyvehaverFakturaID], [IsProcessed], [RowIsChecked])
SELECT DISTINCT
[LøyvehaverID], [KjøretøyID], [Ordrenummer], [c], [År], [Måned], [Betaling (brutto)], [Betaling (netto)], [LøyvehaverFakturaID], [IsProcessed], [RowIsChecked]
FROM
@trips AS o
WHERE
[IsProcessed] = '0'
AND NOT EXISTS (SELECT [Ordrenummer]
FROM [dbo].[trips_non_aggregate] AS i
WHERE i.[Ordrenummer] = o.[Ordrenummer])
SET @rowCount = @@ROWCOUNT
SET @noMatch =
CASE WHEN NOT EXISTS
(SELECT [LøyvehaverID]
FROM [dbo].[trips_non_aggregate] AS i
INNER JOIN [license_holder] AS o ON i.[LøyvehaverID] = o.[Foretaksnavn])
THEN 1 ELSE 0
END
UPDATE [dbo].[trips_non_aggregate]
SET [Betaling (netto)] = (SELECT [Betaling (brutto)] / ([MVAsats] / 100 + 1)
FROM [tblMVAkoder]
WHERE [ID] = 'MVAkode2')
UPDATE [dbo].[trips_non_aggregate]
SET [RowIsChecked] = (SELECT [RowIsChecked] = 0)
COMMIT TRANSACTION
这样当我插入我的数据库时,我能够标记 ColumnA
中不存在于 ColumnB
中的任何条目。但是当我用假数据测试时,结果总是 0
.
为什么会这样?
这是我在 C# 中检查其值的方式:
if (Convert.ToInt32(cmd.Parameters["@noMatch"].Value) == 1)
{
// do something
}
参数方向是否配置得像
cmd.Parameters.Add("@noMatch", SqlDbType.Int);
cmd.Parameters["@noMatch"].Direction = ParameterDirection.Output;
看起来您正在进行某种预检检查,这样如果一条或多条传入的 u_trips_non_agg
记录没有许可证持有人,您根本不会从批次中插入任何数据.我们可以在插入之前检查:
ALTER PROCEDURE [dbo].[p_trips_non_aggregate_insert]
@trips u_trips_non_aggregate readonly,
@rowCount int OUTPUT
WITH RECOMPILE
AS
IF EXISTS (
SELECT null FROM @trips t
WHERE NOT EXISTS (
SELECT null FROM license_holder lh WHERE t.[LøyvehaverID] = lh.[Foretaksnavn]
)
)
THROW 51000, 'At least one of the records being inserted does not have a related licence holder record', 1;
BEGIN TRANSACTION
SET NOCOUNT ON
INSERT INTO [dbo].[trips_non_aggregate]
([LøyvehaverID], [KjøretøyID], [Ordrenummer], [c], [År], [Måned], [Betaling (brutto)], [Betaling (netto)], [LøyvehaverFakturaID], [IsProcessed], [RowIsChecked])
SELECT DISTINCT
[LøyvehaverID], [KjøretøyID], [Ordrenummer], [c], [År], [Måned], [Betaling (brutto)], [Betaling (netto)], [LøyvehaverFakturaID], [IsProcessed], [RowIsChecked]
FROM
@trips AS o
WHERE
[IsProcessed] = '0'
AND NOT EXISTS (SELECT [Ordrenummer]
FROM [dbo].[trips_non_aggregate] AS i
WHERE i.[Ordrenummer] = o.[Ordrenummer])
SET @rowCount = @@ROWCOUNT
SET @noMatch =
CASE WHEN NOT EXISTS
(SELECT [LøyvehaverID]
FROM [dbo].[trips_non_aggregate] AS i
INNER JOIN [license_holder] AS o ON i.[LøyvehaverID] = o.[Foretaksnavn])
THEN 1 ELSE 0
END
UPDATE [dbo].[trips_non_aggregate]
SET [Betaling (netto)] = (SELECT [Betaling (brutto)] / ([MVAsats] / 100 + 1)
FROM [tblMVAkoder]
WHERE [ID] = 'MVAkode2')
UPDATE [dbo].[trips_non_aggregate]
SET [RowIsChecked] = (SELECT [RowIsChecked] = 0)
COMMIT TRANSACTION
一个 EXISTS returns true 或 false 取决于查询是否 returns 任何行。选择什么数据并不重要; EXISTS 只关心是否有任何行。你可以想象它一找到就停止,所以最好不要 运行 大量的百万行查询只是为了知道是否有一行
我们实际上使用了两次,一次是内部的,一次是外部的:
SELECT null FROM @trips t
WHERE NOT EXISTS (
SELECT null FROM license_holder lh WHERE t.[LøyvehaverID] = lh.[Foretaksnavn]
)
第一个到运行的概念在里面:
SELECT null FROM license_holder lh WHERE t.[LøyvehaverID] = lh.[Foretaksnavn]
这是与外部协调的,你可以想象它的工作方式:
For `t.[LøyvehaverID]` = 1
SELECT null FROM license_holder lh WHERE 1 = lh.[Foretaksnavn]
For `t.[LøyvehaverID]` = 2
SELECT null FROM license_holder lh WHERE 2 = lh.[Foretaksnavn]
等等;基本上,对于外部 table @trips
中的每一行,检查 licence_holder
中是否有一行使得 @trips.[LøyvehaverID]
等于 licence_holder.[Foretaksnavn]
.
如果有 是 行,则返回 null
。如果 不是 行,那么 0 行是 returns,这就是 NOT EXISTS 所依据的。也就是说,这个结构:
FROM @trips t
WHERE NOT EXISTS (
SELECT null FROM license_holder lh WHERE t.[LøyvehaverID] = lh.[Foretaksnavn]
)
将查找没有匹配 licence_holder
行的所有 @trips
行
包含在另一个 EXISTS 中的所有内容,一旦找到至少一个“没有 licence_holder 行的 @trips 行”的情况,它就会有效地停止查找
一共是:
EXISTS (
SELECT null FROM @trips t
WHERE NOT EXISTS (
SELECT null FROM license_holder lh WHERE t.[LøyvehaverID] = lh.[Foretaksnavn]
)
)
表示:
@trips 中有一行,而许可证持有者中没有匹配的行
如果是这种情况,然后我们关闭它以抛出异常
我有一个参数 (@noMatch int output
),我根据在下面的存储过程中找到的 CASE
为其赋值:
ALTER PROCEDURE [dbo].[p_trips_non_aggregate_insert]
@trips u_trips_non_aggregate readonly,
@rowCount int OUTPUT,
@noMatch int OUTPUT
WITH RECOMPILE
AS
BEGIN TRANSACTION
SET NOCOUNT ON
INSERT INTO [dbo].[trips_non_aggregate]
([LøyvehaverID], [KjøretøyID], [Ordrenummer], [c], [År], [Måned], [Betaling (brutto)], [Betaling (netto)], [LøyvehaverFakturaID], [IsProcessed], [RowIsChecked])
SELECT DISTINCT
[LøyvehaverID], [KjøretøyID], [Ordrenummer], [c], [År], [Måned], [Betaling (brutto)], [Betaling (netto)], [LøyvehaverFakturaID], [IsProcessed], [RowIsChecked]
FROM
@trips AS o
WHERE
[IsProcessed] = '0'
AND NOT EXISTS (SELECT [Ordrenummer]
FROM [dbo].[trips_non_aggregate] AS i
WHERE i.[Ordrenummer] = o.[Ordrenummer])
SET @rowCount = @@ROWCOUNT
SET @noMatch =
CASE WHEN NOT EXISTS
(SELECT [LøyvehaverID]
FROM [dbo].[trips_non_aggregate] AS i
INNER JOIN [license_holder] AS o ON i.[LøyvehaverID] = o.[Foretaksnavn])
THEN 1 ELSE 0
END
UPDATE [dbo].[trips_non_aggregate]
SET [Betaling (netto)] = (SELECT [Betaling (brutto)] / ([MVAsats] / 100 + 1)
FROM [tblMVAkoder]
WHERE [ID] = 'MVAkode2')
UPDATE [dbo].[trips_non_aggregate]
SET [RowIsChecked] = (SELECT [RowIsChecked] = 0)
COMMIT TRANSACTION
这样当我插入我的数据库时,我能够标记 ColumnA
中不存在于 ColumnB
中的任何条目。但是当我用假数据测试时,结果总是 0
.
为什么会这样?
这是我在 C# 中检查其值的方式:
if (Convert.ToInt32(cmd.Parameters["@noMatch"].Value) == 1)
{
// do something
}
参数方向是否配置得像
cmd.Parameters.Add("@noMatch", SqlDbType.Int);
cmd.Parameters["@noMatch"].Direction = ParameterDirection.Output;
看起来您正在进行某种预检检查,这样如果一条或多条传入的 u_trips_non_agg
记录没有许可证持有人,您根本不会从批次中插入任何数据.我们可以在插入之前检查:
ALTER PROCEDURE [dbo].[p_trips_non_aggregate_insert]
@trips u_trips_non_aggregate readonly,
@rowCount int OUTPUT
WITH RECOMPILE
AS
IF EXISTS (
SELECT null FROM @trips t
WHERE NOT EXISTS (
SELECT null FROM license_holder lh WHERE t.[LøyvehaverID] = lh.[Foretaksnavn]
)
)
THROW 51000, 'At least one of the records being inserted does not have a related licence holder record', 1;
BEGIN TRANSACTION
SET NOCOUNT ON
INSERT INTO [dbo].[trips_non_aggregate]
([LøyvehaverID], [KjøretøyID], [Ordrenummer], [c], [År], [Måned], [Betaling (brutto)], [Betaling (netto)], [LøyvehaverFakturaID], [IsProcessed], [RowIsChecked])
SELECT DISTINCT
[LøyvehaverID], [KjøretøyID], [Ordrenummer], [c], [År], [Måned], [Betaling (brutto)], [Betaling (netto)], [LøyvehaverFakturaID], [IsProcessed], [RowIsChecked]
FROM
@trips AS o
WHERE
[IsProcessed] = '0'
AND NOT EXISTS (SELECT [Ordrenummer]
FROM [dbo].[trips_non_aggregate] AS i
WHERE i.[Ordrenummer] = o.[Ordrenummer])
SET @rowCount = @@ROWCOUNT
SET @noMatch =
CASE WHEN NOT EXISTS
(SELECT [LøyvehaverID]
FROM [dbo].[trips_non_aggregate] AS i
INNER JOIN [license_holder] AS o ON i.[LøyvehaverID] = o.[Foretaksnavn])
THEN 1 ELSE 0
END
UPDATE [dbo].[trips_non_aggregate]
SET [Betaling (netto)] = (SELECT [Betaling (brutto)] / ([MVAsats] / 100 + 1)
FROM [tblMVAkoder]
WHERE [ID] = 'MVAkode2')
UPDATE [dbo].[trips_non_aggregate]
SET [RowIsChecked] = (SELECT [RowIsChecked] = 0)
COMMIT TRANSACTION
一个 EXISTS returns true 或 false 取决于查询是否 returns 任何行。选择什么数据并不重要; EXISTS 只关心是否有任何行。你可以想象它一找到就停止,所以最好不要 运行 大量的百万行查询只是为了知道是否有一行
我们实际上使用了两次,一次是内部的,一次是外部的:
SELECT null FROM @trips t
WHERE NOT EXISTS (
SELECT null FROM license_holder lh WHERE t.[LøyvehaverID] = lh.[Foretaksnavn]
)
第一个到运行的概念在里面:
SELECT null FROM license_holder lh WHERE t.[LøyvehaverID] = lh.[Foretaksnavn]
这是与外部协调的,你可以想象它的工作方式:
For `t.[LøyvehaverID]` = 1
SELECT null FROM license_holder lh WHERE 1 = lh.[Foretaksnavn]
For `t.[LøyvehaverID]` = 2
SELECT null FROM license_holder lh WHERE 2 = lh.[Foretaksnavn]
等等;基本上,对于外部 table @trips
中的每一行,检查 licence_holder
中是否有一行使得 @trips.[LøyvehaverID]
等于 licence_holder.[Foretaksnavn]
.
如果有 是 行,则返回 null
。如果 不是 行,那么 0 行是 returns,这就是 NOT EXISTS 所依据的。也就是说,这个结构:
FROM @trips t
WHERE NOT EXISTS (
SELECT null FROM license_holder lh WHERE t.[LøyvehaverID] = lh.[Foretaksnavn]
)
将查找没有匹配 licence_holder
行的所有 @trips
行
包含在另一个 EXISTS 中的所有内容,一旦找到至少一个“没有 licence_holder 行的 @trips 行”的情况,它就会有效地停止查找
一共是:
EXISTS (
SELECT null FROM @trips t
WHERE NOT EXISTS (
SELECT null FROM license_holder lh WHERE t.[LøyvehaverID] = lh.[Foretaksnavn]
)
)
表示:
@trips 中有一行,而许可证持有者中没有匹配的行
如果是这种情况,然后我们关闭它以抛出异常