我有一个需求,我需要将脏的登台表中的数据插入到干净的登台表中。要注意的是,如果脏暂存表中的任何数据与干净暂存表中相应列的长度/数据类型都不匹配,则应将其捕获并插入错误表中。
所以基本上,让我们假设这是我的脏暂存表-T_DSTG_Employees
包含两列Empid
和EmpName
,并且让我的干净暂存表T_CSTG_Employees
具有相同的两列。干净暂存中的EmpName
列的数据类型为nvarchar(30)
,因此,脏暂存中长度超过30个字符的任何记录都应进入错误表。
在不过度影响性能的情况下执行此操作的最佳方法是什么?在某些情况下,该程序可能会插入近100万条记录。触发器是最优的吗?
答案 0 :(得分:0)
对我来说,我将避免这种方法,而改用其他方法。因此,我将创建存储过程来根据新的干净表要求验证脏暂存表上的所有现有记录,而不是在移动数据时进行验证(这会很麻烦)。然后,将那些不匹配的记录(因此,错误)插入到新表中(类似于Employees_Unmatched)。验证完所有现有记录后,我只需要简单插入并排除不匹配记录表(Employees_Unmatched)中存在的所有记录,然后返回不匹配记录表,并修复记录。根据需要插入到最终表中。
这样,我避免了任何类型的转换错误,并且我确保每个列的关系都是完整的,因为在每个表上可能会有新的或未使用的列或某些结构更改。
验证部分可以是手动的(您为每个表定义自己的逻辑),也可以借助sys.columns
和sys.tables
(链接它们的object_id)来获取两个表列并进行比较它们之间的差异或两者都有(无论哪种方式最适合您的情况)。
答案 1 :(得分:0)
您可以使用触发器或单独的存储过程。我想很显然要添加另一列
ALTER TABLE [dbo].[MyTable]
ADD [IsRowValud] BIT NULL;
然后创建另一个负责验证行的过程。例如:
CREATE PROCEDURE [dbo].[usp_ValidateRows]
AS
BEGIN;
UPDATE [dbo].[MyTable]
SET [IsRowValid] = IIF(LEN(ColA) > 30 OR (TRY_CONVERT(BIGINT, ColB) IS NULL AND Colb IS NOT NULL) OR ..., 0, 1)
WHERE [isRowValid] IS NULL;
END;
然后使用另一个例程在错误暂存表中的isRowValid = 0
和正确数据表中的行isRowValid = 1
中插入行。
您可以在isRowValid
列上创建索引,并测试它是否可以优化某些操作(例如,如果很小范围的数据具有isRowValid = 0
,则可以创建过滤器索引以进行优化插入error
表中。)