我建立了一个简单的数据库SQL Server 2005上运行,现在需要得到它的工作SQL Server 2000的目标是如下的:
- 我收到含有每日数据馈送〜5K记录到一个临时表。
- 当这个插件做一个记录,然后添加到一个名为TRIGGER_DATA表。
- 我已经创建“上插入件”在本表中的触发器,它然后尝试在其中将数据插入到在时间FACT_data表的一个记录。
- 所述FACT_data表被外来键固定到限定了输入可接受的字段可以采取许多DIM表。
- 如果任何记录违反了外键约束刀片出现故障和记录应改为插入Load_error表(它没有外键和所有字段可以为空)。
该触发器有一个主要的try-catch,然后我用一个第二的try-catch在EXEC语句插入到FACT_data表失败的记录直接到Load_error表。
在兼容级别90(即SQL服务器2005)我可以设置XACT_ABORT到触发器内关,一切似乎做工精细 - 下面的代码工作。 然而在兼容级别80个或更少,你不能从一个触发器中设置此参数和我的代码失败,第一次遇到插入误差。
我只在本解决方法的思想是在上表Stage_data插入触发器创建并且每个触发随后处理数据的一行。 我不喜欢但是这种解决方案的数据量相当大,可能会增加,它似乎是一个不错的主意,有5000个触发器在同一时间熄灭。
任何人都可以提供或点我在解决问题的方向吗?
--------- SQL Server 2005的代码片段:
CREATE TRIGGER DataReceived
ON TRIGGER_DATA FOR INSERT AS BEGIN SET NOCOUNT ON;
DECLARE @strfields VARCHAR(4000)DECLARE @ SQL1 VARCHAR(8000); DECLARE @ SQL2 VARCHAR(8000); DECLARE @row_ID VARCHAR(10)
CREATE TABLE #new_ids (sale_id INT )
SET @strfields = 'field1, field2, field3'
-- Insert into FACT_DATA data present in STAGE_DATA
INSERT INTO Log_Data (category, msg, tstamp) VALUES ('General', 'Trigger: Data Received', getdate());
BEGIN TRY
DECLARE Stage_Cursor CURSOR FAST_FORWARD
FOR
SELECT cast(ID as varchar(10)) FROM STAGE_DATA
OPEN Stage_Cursor
FETCH NEXT FROM Stage_Cursor INTO @row_ID
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql1 = ' INSERT FACT_DATA (sale_date_id, '+@strfields+')
OUTPUT INSERTED.sale_id INTO #new_ids'
SET @sql2 = ' SELECT c.sale_date_id,a.* FROM (SELECT '+@strfields+' from STAGE_DATA where ID = '+ @row_id + ') AS a
JOIN
(SELECT sale_date_id,s_date from DIM_calendar) AS c
on a.STORED_DT = c.s_date;'
BEGIN TRY
SET XACT_ABORT OFF
EXEC(@sql1 + @sql2)
END TRY
BEGIN CATCH
--catch records that did not load
SET @sql1 = 'INSERT INTO Load_error ('+@strfields+') '
SET @sql2 = 'SELECT '+@strfields+' from STAGE_DATA where ID = '+ @row_id
EXEC(@sql1 + @sql2)
END CATCH
FETCH NEXT FROM Stage_Cursor INTO @row_ID
END
CLOSE Stage_Cursor
DEALLOCATE Stage_Cursor
--re-enable auto abort
SET XACT_ABORT ON;
--clear tables
TRUNCATE TABLE STAGE_DATA;
TRUNCATE TABLE TRIGGER_DATA;
END TRY
BEGIN CATCH
declare @error int, @message varchar(4000), @xstate int;
select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
if @xstate = -1
rollback;
if @xstate = 1 and @@trancount = 0
rollback;
if @xstate = 1 and @@trancount > 0
rollback ;
INSERT INTO Log_Data (category, msg, tstamp) VALUES ('General', '***FAILED. Trigger: FACT_DATA update', getdate());
raiserror ('DataReceived: %d: %s', 16, 1, @error, @message) ;
return;
END CATCH;
结束
非常感谢
-------------编辑:----------------------------------- ------
我试图修改我的代码在SQL Server 2000中工作(即@@ ERROR检查更换的try-catch)。 然而,它中止失败每次FK冲突发生的时间。 谁能告诉我什么,我做错了什么?
ALTER TRIGGER DataReceived
ON触发INSERT AS BEGIN SET NOCOUNT ON;
DECLARE @row_ID INT
-- Insert into FACT_POS data present in STAGE_DATA
INSERT INTO Log_Data (category, msg, tstamp) VALUES ('General', 'Trigger: Data Received', getdate());
DECLARE @err int
--select 1/0; --generate error
DECLARE Stage_Cursor CURSOR FAST_FORWARD
FOR
SELECT ID FROM STAGE_DATA
OPEN Stage_Cursor
FETCH NEXT FROM Stage_Cursor INTO @row_ID
WHILE @@FETCH_STATUS = 0
BEGIN
--load data
INSERT FACT_DATA (sale_date_id,field1,field2,field3)
SELECT c.sale_date_id,a.* FROM (SELECT field1,field2,field3
from STAGE_DATA where ID = @row_ID) AS a
JOIN
(SELECT sale_date_id,s_date from DIM_calendar) AS c
on a.STORED_DT = c.s_date;
--check error code
SELECT @err=@@error
If @err <>0
BEGIN
--TO DO: catch records that did not load
--raiserror - this should prevent the trigger from aborting the batch
RAISERROR('Error happened', 16, 1)
END
FETCH NEXT FROM Stage_Cursor INTO @row_ID
END
CLOSE Stage_Cursor
DEALLOCATE Stage_Cursor
结束