我想知道为什么我的存储过程花了这么长时间才让专家们跳出来。
该过程仅在通过某些规则的情况下才尝试在主表中插入/更新事务/记录。
如果失败,它将在另一个表中插入/更新事务/记录。
45,000行的过程大约需要5-8分钟。
它原本可以正常运行,但是需要花费很长时间,而且我知道我的表在几个月后将达到100万条记录,所以我不知道要花多长时间。
我将CTE作为一种选择,但不确定如何使用。
注意:实际上,我发现包括一个临时表要比直接查询该临时表更快。
目标是什么
主要目标是确保插入到最终表中的每个记录都是有效的。
如果一条记录有效,那么它将检查该记录在最终表中是否已经存在;如果存在,它将尝试更新该记录(如果详细信息已更改)。如果尚不存在,则会插入新的。
类似地,如果一条记录无效/错误,则检查该记录是否在另一个非最终表中已经存在;如果存在,它将尝试更新该记录(如果详细信息已更改)。如果它不存在,则插入新的。在此表中包含错误消息。
要成为有效记录
注意:验证时发现错误时,我不会立即抛出错误。 @ErrorCode和@ErrorMessage已建立并尽可能具有描述性
SQL代码
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ETL_stage_evestment_performance_to_champ_2.0]
AS
BEGIN
SET NOCOUNT ON;
/*Variable Declaration*/
DECLARE
@BatchImportID UNIQUEIDENTIFIER,
@FileProcessedDate DATETIME,
@FileProcessedUTCDate DATETIME,
@ImportStatus TINYINT,
@ErrorCode VARCHAR(2000),
@ErrorMessage VARCHAR(4000),
@StagingID INT,
@value_date VARCHAR(255),
@firm_id VARCHAR(255),
@product_id VARCHAR(255),
@vehicle_id VARCHAR(255),
@ccy VARCHAR(255),
@reporting_method VARCHAR(255),
@performance_return VARCHAR(255),
@log_return VARCHAR(255)
/*Assign static value for whole one time process*/
SELECT
@BatchImportID = NEWID(),
@FileProcessedDate = GETDATE(),
@FileProcessedUTCDate = GETUTCDATE()
/*Create staging table so we can re-run procedure instead of having to rerun complete task again and again*/
CREATE TABLE #stagingPerformance
(
[index] [BIGINT] NULL,
[value_date] [DATETIME] NULL,
[firm_id] [BIGINT] NULL,
[ccy] [VARCHAR](MAX) NULL,
[product_id] [BIGINT] NULL,
[reporting_method] [VARCHAR](MAX) NULL,
[vehicle_id] [BIGINT] NULL,
[performance_return] [FLOAT] NULL,
[log_return] [FLOAT] NULL
)
CREATE INDEX [IX_EvestmentData_1]
ON #stagingPerformance ([index] ASC, [value_date] ASC, [firm_id] ASC)
-- POPULATE TEMP TABLE
INSERT INTO #stagingPerformance
SELECT
a.[index], a.value_date, a.firm_id, a.ccy,
a.product_id, a.reporting_method, a.vehicle_id,
a.performance_return, a.log_return
FROM
CHAMP_DW.dbo.champ_dw_staging_evestment_performance a
/*While loop started to get process record one by one*/
WHILE EXISTS (SELECT 1 FROM #stagingPerformance AS FHD WITH (NOLOCK))
BEGIN
BEGIN TRY
BEGIN TRANSACTION
/*To assign 1 record values to respective variables*/
SELECT TOP 1
@StagingID = FHD.[index],
@firm_id = NULLIF(FHD.[firm_id],''),
@product_id = NULLIF(FHD.[product_id],''),
@vehicle_id = NULLIF(FHD.[vehicle_id],''),
@value_date = NULLIF(FHD.[value_date],''),
@reporting_method = NULLIF(FHD.[reporting_method],''),
@ccy = NULLIF(FHD.[ccy],''),
@performance_return = NULLIF(FHD.[performance_return],''),
@log_return = NULLIF(FHD.[log_return],'')
FROM
#stagingPerformance AS FHD WITH (NOLOCK)
ORDER BY
FHD.[index]
/*Record wise validation start*/
IF @reporting_method IS NOT NULL
AND NOT EXISTS(SELECT 1 WHERE @reporting_method in ('Gross', 'Net', 'Index'))
BEGIN
SELECT
@ErrorCode = ISNULL(@ErrorCode,'') + ',' + '115',
@ErrorMessage = ISNULL(@ErrorMessage,'') + ',' + 'Reporting Method is invalid'
END
IF @value_date IS NOT NULL AND ISDATE(@value_date) = 0
BEGIN
SELECT
@ErrorCode = ISNULL(@ErrorCode,'') + ',' + '106',
@ErrorMessage = ISNULL(@ErrorMessage,'') + ',' + 'Invalid value of Value Date.'
END
IF @performance_return IS NOT NULL
AND ISNUMERIC(@performance_return) = 0
BEGIN
SELECT
@ErrorCode = ISNULL(@ErrorCode,'') + CASE WHEN @ErrorCode LIKE '%112%' THEN '' ELSE ',' + '112' END,
@ErrorMessage = ISNULL(@ErrorMessage,'') + ',' + 'Invalid value of performance.'
END
IF @log_return IS NOT NULL AND ISNUMERIC(@log_return) = 0
BEGIN
SELECT
@ErrorCode = ISNULL(@ErrorCode,'') + CASE WHEN @ErrorCode LIKE '%112%' THEN '' ELSE ',' + '112' END,
@ErrorMessage = ISNULL(@ErrorMessage,'') + ',' + 'Invalid value of log_return.'
END
IF @firm_id IS NOT NULL
AND NOT EXISTS(SELECT 1
FROM CHAMP_DW.dbo.champ_dw_fund_manager_mapping AS DFM WITH (NOLOCK)
WHERE DFM.evestment_fund_manager_id = @firm_id)
BEGIN
SELECT
@ErrorCode = ISNULL(@ErrorCode,'') + ',' + '113',
@ErrorMessage = ISNULL(@ErrorMessage,'') + ',' + 'Firm ID not Mapped'
END
IF @product_id IS NOT NULL AND NOT EXISTS(SELECT 1 FROM dbo.champ_dw_product_mapping AS DAM WITH (NOLOCK) WHERE DAM.evestment_product_id=@product_id)
BEGIN
SELECT
@ErrorCode = ISNULL(@ErrorCode,'') + ',' + '114',
@ErrorMessage = ISNULL(@ErrorMessage,'') + ',' + 'Product ID is not Mapped'
END
IF @ccy IS NOT NULL AND NOT EXISTS(SELECT 1 FROM [dbo].champ_dw_dim_currency AS DC WITH (NOLOCK) WHERE DC.currency = @ccy) BEGIN
SELECT
@ErrorCode = ISNULL(@ErrorCode,'') + ',' + '112',
@ErrorMessage = ISNULL(@ErrorMessage,'') + ',' + 'Invalid CCY'
END
SELECT
@ErrorCode = NULLIF(STUFF(@ErrorCode,1,1,''),''),
@ErrorMessage = NULLIF(STUFF(@ErrorMessage,1,1,''),'')
IF @ErrorMessage IS NOT NULL
BEGIN
;THROW 50552,'VALIDATION RAISE ERROR.',1
END
/*Record wise validation end*/
/*To get unique record value based on columns*/
DECLARE
@performance_id bigint = 0,
@vfirm_id INT,
@vproduct_id INT,
@vvehicle_id INT,
@vvalue_date datetime2,
@vreporting_method nvarchar(max),
@vccy nvarchar(3),
@vperformance_return float,
@vlog_return float,
@map_firm_id INT,
@map_product_id INT
SELECT
@vfirm_id = TRY_PARSE(@firm_id AS INT),
@vproduct_id = TRY_PARSE(@product_id AS INT),
@vvehicle_id = TRY_PARSE(@vehicle_id AS INT),
@vvalue_date = TRY_PARSE(@value_date AS datetime2),
@vreporting_method = @reporting_method,
@vccy = cast(@ccy as nvarchar(3)),
@vperformance_return = TRY_PARSE(@performance_return AS float),
@vlog_return = TRY_PARSE(@log_return AS float)
SELECT
@map_firm_id = (SELECT fund_manager_mapping_id FROM CHAMP_DW.dbo.champ_dw_fund_manager_mapping fm WHERE fm.evestment_fund_manager_id = @vfirm_id),
@map_product_id = (SELECT product_mapping_id FROM CHAMP_DW.dbo.champ_dw_product_mapping fp WHERE fp.product_mapping_id=@vvehicle_id)
SELECT
@performance_id = FFHD.performance_id
FROM dbo.[champ_dw_fact_performance] AS FFHD WITH (NOLOCK)
WHERE FFHD.fund_manager_id = @map_firm_id
AND FFHD.product_id = @map_product_id
AND FFHD.value_date = @vvalue_date
AND FFHD.data_source = 'eVestment'
AND FFHD.ccy_id = @vccy
AND FFHD.reporting_method = @vreporting_method
IF @performance_id IS NOT NULL or @performance_id = 0
BEGIN
/*Update record, if any value has different then already exist in DB.*/
UPDATE FFHD
SET
FFHD.ccy_id = @ccy,
FFHD.performance_return = @vperformance_return,
FFHD.log_return = @vlog_return
FROM dbo.[champ_dw_fact_performance] AS FFHD WITH (NOLOCK)
WHERE FFHD.performance_id = @performance_id
AND
(
ISNULL(FFHD.performance_return,'0') <> @vperformance_return
OR
ISNULL(FFHD.log_return,'0') <> @vlog_return
)
END
ELSE
BEGIN
/*Add new record */
INSERT INTO dbo.[champ_dw_fact_performance]
(
value_date,
reporting_method,
valuation_quality,
data_source,
performance_return,
log_return,
ccy_id,
fund_manager_id,
product_id
)
SELECT
@vvalue_date AS value_date,
@vreporting_method AS reporting_method,
'Actual' as valuation_quality,
'eVestment' as data_source,
@vperformance_return AS performance_return,
@vlog_return AS log_return,
@vccy AS ccy_id,
@map_firm_id AS fund_manager_id_id,
@map_product_id AS product_id_id
END
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION
END
BEGIN TRANSACTION
DECLARE
@ERROR_MESSAGE NVARCHAR(4000)
SELECT
@ERROR_MESSAGE = ERROR_MESSAGE()
IF @ERROR_MESSAGE <> 'VALIDATION RAISE ERROR.'
BEGIN
SELECT
@ErrorCode = ISNULL(@ErrorCode,'') + CASE WHEN ISNULL(@ERROR_MESSAGE,'') <> '' THEN ',' + '999' ELSE '' END,
@ErrorMessage = ISNULL(@ErrorMessage,'') + CASE WHEN ISNULL(@ERROR_MESSAGE,'') <> '' THEN ',' + CONVERT(VARCHAR(4000),@ERROR_MESSAGE) ELSE '' END
END
SELECT
@ErrorCode = NULLIF(CASE WHEN @ErrorCode LIKE '%999%' THEN STUFF(@ErrorCode,1,1,'') ELSE @ErrorCode END,''),
@ErrorMessage = NULLIF(CASE WHEN @ErrorCode LIKE '%999%' THEN STUFF(@ErrorMessage,1,1,'') ELSE @ErrorMessage END,'')
/*To add failed record to table*/
SELECT
@performance_id = FFHD.AutoLogID
FROM dbo.champ_dw_evestment_performance AS FFHD WITH (NOLOCK)
WHERE FFHD.firm_id = @vfirm_id
AND FFHD.product_id = @vproduct_id
AND FFHD.vehicle_id = @vvehicle_id
AND FFHD.value_date = @vvalue_date
AND FFHD.ccy_id = @vccy
AND FFHD.reporting_method = @vreporting_method
IF @performance_id IS NOT NULL or @performance_id = 0
BEGIN
/*Update failed record, if any value has different then already exist in DB.*/
UPDATE FFHD
SET
FFHD.performance_return = @vperformance_return,
FFHD.log_return = @vlog_return,
FFHD.BatchImportID = @BatchImportID,
FFHD.FileProcessedDate = @FileProcessedDate,
FFHD.FileProcessedUTCDate = @FileProcessedUTCDate,
FFHD.ErrorCode = @ErrorCode,
FFHD.ErrorMessage = @ErrorMessage
FROM dbo.champ_dw_evestment_performance AS FFHD WITH (NOLOCK)
WHERE FFHD.AutoLogID = @performance_id
AND
(
ISNULL(FFHD.performance_return,'0') <> @vperformance_return
OR
ISNULL(FFHD.log_return,'0') <> @vlog_return
)
END
ELSE
BEGIN
/*Add new record */
INSERT INTO dbo.champ_dw_evestment_performance
(
BatchImportID,
FileProcessedDate,
FileProcessedUTCDate,
ImportStatus,
ErrorCode,
ErrorMessage,
value_date,
reporting_method,
ccy_id,
performance_return,
log_return,
firm_id,
product_id,
vehicle_id
)
SELECT
@BatchImportID AS BatchImportID,
@FileProcessedDate AS FileProcessedDate,
@FileProcessedUTCDate AS FileProcessedUTCDate,
0 AS ImportStatus,
@ErrorCode AS ErrorCode,
@ErrorMessage AS ErrorMessage,
@value_date AS value_date,
@reporting_method AS reporting_method,
@ccy AS ccy_id,
@performance_return AS performance_return,
@log_return AS log_return,
@firm_id AS firm_id,
@product_id AS product_id,
@vehicle_id AS vehicle_id
END
COMMIT TRANSACTION
END CATCH;
DELETE FHD
FROM #stagingPerformance AS FHD
WHERE FHD.[index] = @StagingID
SELECT
@performance_id = NULL,
@StagingID = NULL,
@firm_id = NULL,
@product_id = NULL,
@vehicle_id = NULL,
@value_date = NULL,
@reporting_method = NULL,
@ccy = NULL,
@performance_return = NULL,
@log_return = NULL,
@ImportStatus = NULL,
@ErrorCode = NULL,
@ErrorMessage = NULL
END
SELECT @BatchImportID as 'BatchID'
DROP TABLE #stagingPerformance
END
更新工作解决方案-从20分钟下调6秒
ALTER PROCEDURE [dbo].[ETL_stage_evestment_performance_to_champ_2.0_New]
AS
BEGIN
SET NOCOUNT ON;
DECLARE
@BatchImportID UNIQUEIDENTIFIER,
@FileProcessedDate DATETIME,
@FileProcessedUTCDate DATETIME,
@ImportStatus TINYINT,
@ErrorCode VARCHAR(2000),
@ErrorMessage VARCHAR(4000),
@StagingID INT,
@value_date VARCHAR(255),
@firm_id VARCHAR(255),
@product_id VARCHAR(255),
@vehicle_id VARCHAR(255),
@ccy VARCHAR(255),
@reporting_method VARCHAR(255),
@performance_return VARCHAR(255),
@log_return VARCHAR(255)
/*Assign static value for whole one time process*/
SELECT
@BatchImportID = NEWID(),
@FileProcessedDate = GETDATE(),
@FileProcessedUTCDate = GETUTCDATE()
/*Create staging table so we can re-run procedure instead of having to rerun complete task again and again*/
DECLARE @stagingPerformance TABLE (
[index] [BIGINT] NULL,
[value_date] [DATETIME] NULL,
[firm_id] [BIGINT] NULL,
[ccy] [VARCHAR](MAX) NULL,
[product_id] [BIGINT] NULL,
[reporting_method] [VARCHAR](MAX) NULL,
[vehicle_id] [BIGINT] NULL,
[performance_return] [FLOAT] NULL,
[log_return] [FLOAT] NULL,
[ErrorCode] NVARCHAR(MAX),
[ErrorMessage] NVARCHAR(MAX)
)
-- POPULATE 1st Staging Table with Data and Error Codes and Error Messages
INSERT INTO @stagingPerformance
SELECT
a.[index],
NULLIF(a.value_date,''),
NULLIF(a.firm_id,''),
NULLIF(a.ccy,''),
NULLIF(a.product_id,''),
NULLIF(a.reporting_method,''),
NULLIF(a.vehicle_id,''),
NULLIF(a.performance_return,''),
NULLIF(a.log_return,''),
'' as ErrorCode,
'' as ErrorMessage
FROM
CHAMP_DW.dbo.champ_dw_staging_evestment_performance a
/* Have one update, but set one variable concatenated
or alternatively change the below to have multiple updates per condition and then you are able to set multiple variables per condition*/
UPDATE @stagingPerformance
SET ErrorCode =
CASE WHEN reporting_method IS NOT NULL AND reporting_method IN ('Gross', 'Net', 'Index')
THEN ''
ELSE ','+'115'
END
+
CASE WHEN value_date IS NOT NULL AND ISDATE(value_date) = 1
THEN ''
ELSE ','+'106'
END
+
CASE WHEN firm_id IS NOT NULL AND DFM.evestment_fund_manager_id IS NOT NULL
THEN ''
ELSE ','+'113'
END
+
CASE WHEN product_id IS NOT NULL AND DAM.evestment_product_id IS NOT NULL
THEN ''
ELSE ','+'114'
END
+
CASE WHEN ccy IS NOT NULL AND DC.currency IS NOT NULL
THEN ''
ELSE ','+'112'
END
,ErrorMessage=
CASE WHEN reporting_method IS NOT NULL AND reporting_method IN ('Gross', 'Net', 'Index')
THEN ''
ELSE ','+'Invalid Reporting Method'--115
END
+
CASE WHEN value_date IS NOT NULL AND ISDATE(value_date) = 1
THEN ''
ELSE ','+'Invalid Value Date'--106
END
+
CASE WHEN firm_id IS NOT NULL AND DFM.evestment_fund_manager_id IS NOT NULL
THEN ''
ELSE ','+'Unmapped Firm' --113
END
+
CASE WHEN product_id IS NOT NULL AND DAM.evestment_product_id IS NOT NULL
THEN ''
ELSE ','+'Unmapped Product' --114
END
+
CASE WHEN ccy IS NOT NULL AND DC.currency IS NOT NULL
THEN ''
ELSE ','+'Invalid CCY' --112
END
FROM
@stagingPerformance a
LEFT JOIN CHAMP_DW.dbo.champ_dw_fund_manager_mapping AS DFM ON DFM.evestment_fund_manager_id = a.firm_id
LEFT JOIN CHAMP_DW.dbo.champ_dw_product_mapping DAM ON DAM.evestment_product_id = a.product_id
LEFT JOIN CHAMP_DW.dbo.champ_dw_dim_currency AS DC WITH (NOLOCK) ON DC.currency = a.ccy
/* Remove leading "," */
UPDATE @stagingPerformance
SET ErrorCode = STUFF(ErrorCode,1,1,'')
WHERE ErrorCode LIKE ',%'
UPDATE @stagingPerformance
SET ErrorMessage= STUFF(ErrorMessage,1,1,'')
WHERE ErrorMessage LIKE ',%'
--------------------------------------------------------------------------------------------------------------------
/* RECORD HANDLING (Records without validation errors) */
--------------------------------------------------------------------------------------------------------------------
DECLARE @stagingPerformanceNoError TABLE (
do_create bit,
performance_id BIGINT,
vfirm_id BIGINT NULL,
vproduct_id BIGINT,
vvehicle_id BIGINT,
vvalue_date datetime2,
vreporting_method nvarchar(max),
vccy nvarchar(3),
vperformance_return float,
vlog_return float,
map_firm_id INT,
map_product_id INT
)
/* Move from Staging Table 1 to Staging Table 2 all records without errors */
INSERT INTO @stagingPerformanceNoError
SELECT
CASE WHEN FFHD.performance_id IS NOT NULL AND
(
ISNULL(FFHD.performance_return,'0') <> a.performance_return
OR
ISNULL(FFHD.log_return,'0') <> a.log_return
)
THEN 0 ELSE 1 END AS do_create,--create 1=update 0 /*Same Criteria as before to decide when to Insert or when to Update */
FFHD.performance_id as performance_id,
a.firm_id,
a.product_id,
a.vehicle_id,
a.value_date,
a.reporting_method,
a.ccy, --char 3
a.performance_return,
a.log_return,
fm.fund_manager_mapping_id as map_firm_id,--map_firm_id
fp.product_mapping_id as map_product_id--map_product_id
FROM @stagingPerformance a
LEFT JOIN CHAMP_DW.dbo.champ_dw_fund_manager_mapping fm ON fm.evestment_fund_manager_id = a.firm_id
LEFT JOIN CHAMP_DW.dbo.champ_dw_product_mapping fp ON fp.product_mapping_id=a.vehicle_id
LEFT JOIN CHAMP_DW.dbo.[champ_dw_fact_performance] AS FFHD
ON FFHD.fund_manager_id = fm.fund_manager_mapping_id
AND FFHD.product_id = fp.product_mapping_id
AND FFHD.value_date = a.value_date
AND FFHD.data_source = 'eVestment'
AND FFHD.ccy_id = ccy
AND FFHD.reporting_method = a.reporting_method
WHERE a.ErrorCode='' /* Only records without errors are moved to staging table 2*/
/*Update record, if any value has different then already exist in DB.*/
UPDATE CHAMP_DW.dbo.[champ_dw_fact_performance]
SET
ccy_id = a.vccy,
performance_return = a.vperformance_return,
log_return = a.vlog_return
FROM dbo.[champ_dw_fact_performance] AS FFHD WITH (NOLOCK)
INNER JOIN @stagingPerformanceNoError a ON a.performance_id=FFHD.performance_id
WHERE do_create=0 /*Update*/
/*Add new record */
INSERT INTO dbo.[champ_dw_fact_performance]
(
value_date,
reporting_method,
valuation_quality,
data_source,
performance_return,
log_return,
ccy_id,
fund_manager_id,
product_id
)
SELECT
vvalue_date AS value_date,
vreporting_method AS reporting_method,
'Actual' as valuation_quality,
'eVestment' as data_source,
vperformance_return AS performance_return,
vlog_return AS log_return,
vccy AS ccy_id,
map_firm_id AS fund_manager_id_id,
map_product_id AS product_id_id
FROM @stagingPerformanceNoError
WHERE do_create=1 /*Insert*/
AND performance_id IS NULL
--------------------------------------------------------------------------------------------------------------------
/* ERROR HANDLING - Records with Validation ERRORS */
--------------------------------------------------------------------------------------------------------------------
DECLARE @stagingPerformanceError TABLE (
[performance_id] [BIGINT] NULL,
[index] [BIGINT] NULL,
[value_date] [DATETIME] NULL,
[firm_id] [BIGINT] NULL,
[ccy] [VARCHAR](MAX) NULL,
[product_id] [BIGINT] NULL,
[reporting_method] [VARCHAR](MAX) NULL,
[vehicle_id] [BIGINT] NULL,
[performance_return] [FLOAT] NULL,
[log_return] [FLOAT] NULL,
[ErrorCode] NVARCHAR(MAX),
[ErrorMessage] NVARCHAR(MAX)
)
-- POPULATE Error Table
INSERT INTO @stagingPerformanceError
SELECT
NULL, --performance_id
a.[index],
NULLIF(a.value_date,''),
NULLIF(a.firm_id,''),
NULLIF(a.ccy,''),
NULLIF(a.product_id,''),
NULLIF(a.reporting_method,''),
NULLIF(a.vehicle_id,''),
NULLIF(a.performance_return,''),
NULLIF(a.log_return,''),
NULLIF(a.ErrorCode,''),
NULLIF(a.ErrorMessage,'')
FROM
@stagingPerformance a
WHERE a.ErrorCode<>''
UPDATE @stagingPerformanceError
SET performance_id= FFHD.AutoLogID
FROM @stagingPerformanceError a
INNER JOIN dbo.champ_dw_evestment_performance AS FFHD
ON FFHD.firm_id = a.firm_id
AND FFHD.product_id = a.product_id
AND FFHD.vehicle_id = a.vehicle_id
AND FFHD.value_date = a.value_date
AND FFHD.ccy_id = a.ccy
AND FFHD.reporting_method = a.reporting_method
/*Update failed record, if any value has different then already exist in DB.*/
UPDATE FFHD
SET
FFHD.performance_return = a.performance_return,
FFHD.log_return = a.log_return,
FFHD.BatchImportID = @BatchImportID,
FFHD.FileProcessedDate = @FileProcessedDate,
FFHD.FileProcessedUTCDate = @FileProcessedUTCDate,
FFHD.ErrorCode = @ErrorCode,
FFHD.ErrorMessage = @ErrorMessage
FROM dbo.champ_dw_evestment_performance AS FFHD
INNER JOIN @stagingPerformanceError a ON FFHD.AutoLogID = a.performance_id
WHERE FFHD.AutoLogID = a.performance_id
AND
(
ISNULL(FFHD.performance_return,'0') <> a.performance_return
OR
ISNULL(FFHD.log_return,'0') <> a.log_return
)
AND a.performance_id IS NOT NULL
/*Add new record */
INSERT INTO dbo.champ_dw_evestment_performance
(
BatchImportID,
FileProcessedDate,
FileProcessedUTCDate,
ImportStatus,
ErrorCode,
ErrorMessage,
value_date,
reporting_method,
ccy_id,
performance_return,
log_return,
firm_id,
product_id,
vehicle_id
)
SELECT
@BatchImportID AS BatchImportID,
@FileProcessedDate AS FileProcessedDate,
@FileProcessedUTCDate AS FileProcessedUTCDate,
0 AS ImportStatus,
A.ErrorCode AS ErrorCode,
a.ErrorMessage AS ErrorMessage,
a.value_date AS value_date,
a.reporting_method AS reporting_method,
a.ccy AS ccy_id,
a.performance_return AS performance_return,
a.log_return AS log_return,
a.firm_id AS firm_id,
a.product_id AS product_id,
a.vehicle_id AS vehicle_id
FROM @stagingPerformanceError a
WHERE a.performance_id IS NULL
END
答案 0 :(得分:4)
以下是一些使用基于集合的操作而不是RBAR的示例。这些只是一口气完成了整个操作,而不是慢慢地循环。
由于您的proc的复杂性,我可能错过了一些东西,但这给了您一个主意
第一个很简单-只需根据where子句更新一条记录
update dbo.champ_dw_evestment_performance
set ErrorMessage = ISNULL(ErrorMessage,'') + 'Reporting Method is invalid'
where reporting_method NOT IN ('Gross', 'Net', 'Index')
and reporting_method IS NOT NULL
这一次标记了所有记录 而不是慢慢地循环
第二个示例是再次更新的示例,其中带有一个where,但是该示例在存在内部具有“关联”联接
update TGT
set ErrorMessage = ISNULL(ErrorMessage,'') + 'Firm ID not Mapped'
FROM dbo.champ_dw_evestment_performance AS TGT
WHERE NOT EXISTS (
SELECT * FROM CHAMP_DW.dbo.champ_dw_fund_manager_mapping AS DFM
WHERE DFM.evestment_fund_manager_id = TGT.firm_id
)
您应该能够使用这两个概念从循环中删除很多这些更新。
关于dbo.[champ_dw_fact_performance]
的更新。.我不能跟随您在这里所做的事情,但是我敢肯定,即使其中有一些加入,您也可以在一条语句中做到这一点。它。
我认为我没有在您的代码中看到任何联接。您真的需要了解这些。
因此,如果这对您有意义,并且您希望我攻击champ_dw_fact_performance更新,请告诉我。解开它有点费力