免责声明:我不是SQL专家。我想在将记录插入父表之前将其插入子表中。 (在说我开始怀疑这是否是一个好主意之后。)父表记录包含对子表记录的引用,并且所述引用不能为空。这需要我先插入子表,然后在辅助插入期间链接到父表。
无论如何,由于某些原因,此代码在IdentifyingData(子)表中随机生成孤立记录,例如,他们在FraudScore(父)表中没有条目,即使它们应该。
这就是为什么我很困惑。在尝试解决此问题时,我开始将@tempFraudScore表的内容转储到物理审计表中,以便我可以确切地看到数据转换期间发生了什么。当我从@tempFraudScore切换插入FraudScore的以下代码到审计表中插入时,所有子记录都成功获得创建的父记录。这对我来说毫无意义。
insert into IdentifyingData (EntryDateTime, IdentifyingDataTypeId, Value, Source)
select distinct GETDATE(), tfs.IdentifyingDataTypeId, tfs.Value, 'SSIS'
from @tempFraudScore tfs
where not exists (
select id.IdentifyingDataTypeId, id.Value
from IdentifyingData id
where tfs.IdentifyingDataTypeId = id.IdentifyingDataTypeId
and tfs.Value = id.Value
);
update tfs
set tfs.IdentifyingDataId = id.Id
from @tempFraudScore tfs
inner join IdentifyingData id on
tfs.Value = id.Value and
tfs.IdentifyingDataTypeId = id.IdentifyingDataTypeId;
insert into FraudScore (EntryDateTime, FraudCriteriaId, AccountId, IdentifyingDataId, Score, Source)
select distinct
GETDATE() EntryDateTime,
tfs.FraudCriteriaId,
tfs.AccountId,
tfs.IdentifyingDataId,
tfs.Score,
'SSIS'
from @tempFraudScore tfs
inner join FraudCriteria fc on
tfs.FraudCriteriaId = fc.Id
and fc.UniqueEntryPeriod = 0
where not exists (
select fs.AccountId, fs.FraudCriteriaId, fs.IdentifyingDataId
from FraudScore fs
where tfs.AccountId = fs.AccountId
and tfs.FraudCriteriaId = fs.FraudCriteriaId
and tfs.IdentifyingDataId = fs.IdentifyingDataId
);
@tempFraudScore预先填充了除IdentifyingDataId之外的所有必要字段;必须首先插入IdentifyingData,然后使用创建的ID更新变量表。下面是变量表的结构:
declare @tempFraudScore table(
FraudCriteriaId int,
AccountId bigint,
IdentifyingDataId bigint,
IdentifyingDataTypeId smallint,
Value varchar(100),
Score int
);
有人可以告诉我可能导致这些孤立的IdentifyingData记录的原因吗?我应该重新考虑这两个表之间的关系是如何构建的吗?我正在尝试做一些事情,以便一旦某个IdentifyingData记录被放入系统,它就不会重复;它只会被新创建的FraudScore记录引用。
修改 附件是审计表中的屏幕截图,显示了单个值的数据转换进度(值列对于这些记录是相同的值;我为了隐私而模糊了它)。请注意,尽管有消息“Post-FraudScore Insert”,但有问题的记录实际上从未插入到FraudScore表中。
Edit2(2/6/2018):我在尝试解决此问题时已将以下代码添加到存储过程中。我有一个值(99999)出现在_Audit表的Value列中,但不是第二个表的Value列,尽管代码只是将所有数据从同一个源转储到这两个表中!我不确定它是否重要,但是这个存储过程从SSIS包的执行SQL任务开始,其IsolationLevel为“Serializable”。也就是说,我没有明确地在代码中的任何地方使用事务,并且该Execute SQL Task的TransactionOption被设置为“Supported”。我不知道这是否与这个问题有关。
insert into FraudScoreIdentifyingData_Audit
select 'Post-IdentifyingData Update', GETDATE(), FraudCriteriaId, AccountId, IdentifyingDataId, IdentifyingDataTypeId, Value, Score
from @tempFraudScore;
insert into FraudScoreIdentifyingData
select GETDATE(), FraudCriteriaId, AccountId, IdentifyingDataId, IdentifyingDataTypeId, Value, Score, 1
from @tempFraudScore;
以下是两个表的模式:
答案 0 :(得分:0)
不能说出造成问题的原因。
Parent Table=FraudScore
Child Table=IdentifyingData
它们是如何相关的?首先你在FraudScore
中插入记录,然后使用输出子句,如果你有多个插入,在IdentifyingData
中插入记录
但即使问题因此而无法解决,这也是使用OUTPUT clause
的理想情况。
--data type similar to IdentifyingData
declare @tbl table(Id int,Value int,IdentifyingDataTypeId int)
declare @CurrentDateTime datetime=GETDATE()
begin try
begin transaction
insert into IdentifyingData (EntryDateTime, IdentifyingDataTypeId
, Value, Source)
OUTPUT INSERTED.Id, INSERTED.Value, INSERTED.IdentifyingDataTypeId
INTO @tbl
select distinct @CurrentDateTime, tfs.IdentifyingDataTypeId
, tfs.Value, 'SSIS'
from @tempFraudScore tfs
where not exists (
select id.IdentifyingDataTypeId, id.Value
from IdentifyingData id
where tfs.IdentifyingDataTypeId = id.IdentifyingDataTypeId
and tfs.Value = id.Value
);
update tfs
set tfs.IdentifyingDataId = id.Id
from @tempFraudScore tfs
inner join @tbl id on
tfs.Value = id.Value and
tfs.IdentifyingDataTypeId = id.IdentifyingDataTypeId;
insert into FraudScore (EntryDateTime, FraudCriteriaId, AccountId,
IdentifyingDataId, Score, Source)
select distinct
@CurrentDateTime EntryDateTime,
tfs.FraudCriteriaId,
tfs.AccountId,
tfs.IdentifyingDataId,
tfs.Score,
'SSIS'
from @tempFraudScore tfs
inner join FraudCriteria fc on
tfs.FraudCriteriaId = fc.Id
and fc.UniqueEntryPeriod = 0
where not exists (
select fs.AccountId, fs.FraudCriteriaId, fs.IdentifyingDataId
from FraudScore fs
where tfs.AccountId = fs.AccountId
and tfs.FraudCriteriaId = fs.FraudCriteriaId
and tfs.IdentifyingDataId = fs.IdentifyingDataId
);
COMMIT
end TRY
begin CATCH
if(@@trancount>0)
ROLLBACK
end CATCH
答案 1 :(得分:0)
事实证明,我的一个大型存储过程中隐藏了一个删除语句,这些语句写错了导致问题。
在寻找这个问题的原因时,我还有一位DBA和我坐在一起,他确定了我的SSIS流程的一部分,即重组索引;但它正在这样做,因为程序包继续运行并填充所有必要的基础表(包括具有孤立记录的表)。据他说,重组或重建表上的索引,同时尝试向这些表添加或删除记录也可能导致此问题;虽然在我的具体情况下,它是错误编写的单个删除语句。