[更新:2009年2月20日]我找到了解决这个问题的一个非常简单的解决方案。
CREATE TRIGGER TriggerClaims_History on Claims
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
INSERT INTO Claims_History
SELECT name, status, claim_date
FROM Claims
EXCEPT SELECT name, status, claim_date FROM Claims_History
END
GO
我正在为我正在处理的项目站起来一个SQL Server数据库。重要信息:我有3个表 - 注册,取消和索赔。服务器上有文件每天填充这些表。这些文件不是增量(即每天放在服务器上的每个新文件都包含来自所有以前文件的数据),因此,我可以简单地删除所有表,创建表,然后每天从文件中填充表。我的问题是关于我的索赔表 - 因为每晚会丢弃和创建表格,我需要一种方法来跟踪所有不同的状态变化。
我正在努力找出解决这个问题的最佳方法。
我正在考虑创建一个每晚都不会删除的claim_history表。基本上我希望每次将初始新记录添加到声明表时填充claim_history表。然后我想扫描声明表并在claim_history表中添加一行,当且仅当状态列中有更改时(即claims.status!= claims_history.status)。
第1天:
select * from claims
id | name | status
1 | jane doe | received
select * from claims_history
id | name | status | timestamp
1 | jane doe | received | datetime
第2天:
select * from claims
id | name | status
1 | jane doe | processed
select * from claims_history
id | name | status | timestamp
1 | jane doe | received | datetime
1 | jane doe | processed | datetime
是否有可以执行此操作的SQL脚本?我还想在每次添加新行时(状态更改)自动在claim_history表中填充时间戳字段。我知道我可以写一个python脚本来处理这样的事情,但是如果可能的话我想把它保存在SQL中。谢谢。
根据你的问题,你需要在更新列claim.status之后创建一个触发器,这很简单,使用此链接来了解并查看如何进行简单的触发点击此处create asimple sql server trigger
然后好像在查询中操作dateTime有很多问题,建议你使用UNIX时间而不是使用datetime你可以使用Long或bigInt UNix时间存储日期作为数字来知道当前时间简单使用查询SELECT UNIX_TIMESTAMP ()
一种非常常见的方法是使用临时表和生产(或最终)表。所有ETL都将截断并加载登台表(volatile),然后执行存储过程,该过程仅将新记录添加到最终表中。这要求您以这种方式处理的所有数据都具有某种形式的密钥,可以明确地标识一行。
如果您的文件突然改变格式或格式错误会怎样?您将删除表,并且在修复ETL之前无法将其加载。这种方法可以避免这种情况,因为加载登台表时进程会失败,并且不会影响最终表。您还可以出于历史原因保留已删除的记录,而不是删除它们。
我更喜欢将登台表分成适当的架构,例如:
CREATE SCHEMA Staging
GO
CREATE TABLE Staging.Claims (
ID INT,
Name VARCHAR(100),
Status VARCHAR(100))
现在,您将从文件中加载到这些临时表中的所有负载,首先截断它们:
TRUNCATE TABLE Staging.Claims
BULK INSERT Staging.Claims
FROM '\\SomeFile.csv'
WITH
--...
加载此表后,您将执行一个特定的SP,它会在暂存内容和最终表之间添加增量。您可以在此处添加所需的逻辑,例如仅插入新记录,或插入已在另一个表上更新的现有值。例如:
CREATE TABLE dbo.Claims (
ClaimAutoID INT IDENTITY PRIMARY KEY,
ClaimID INT,
Name VARCHAR(100),
Status VARCHAR(100),
WasDeleted BIT DEFAULT 0,
ModifiedDate DATETIME,
CreatedDate DATETIME DEFAULT GETDATE())
GO
CREATE PROCEDURE Staging.UpdateClaims
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
-- Update changed values
UPDATE C SET
Name = S.Name,
Status = S.Status,
ModifiedDate = GETDATE()
FROM
Staging.Claims AS S
INNER JOIN dbo.Claims AS C ON S.ID = C.ClaimID -- This has to be by the key columns
WHERE
ISNULL(C.Name, '') <> ISNULL(S.Name, '') AND
ISNULL(C.Status, '') <> ISNULL(S.Status, '')
-- Insert new records
INSERT INTO dbo.Claims (
ClaimID,
Name,
Status)
SELECT
ClaimID = S.ID,
Name = S.Name,
Status = S.Status
FROM
Staging.Claims AS S
WHERE
NOT EXISTS (SELECT 'not yet loaded' FROM dbo.Claims AS C WHERE S.ID = C.ClaimID) -- This has to be by the key columns
-- Mark deleted records as deleted
UPDATE C SET
WasDeleted = 1,
ModifiedDate = GETDATE()
FROM
dbo.Claims AS C
WHERE
NOT EXISTS (SELECT 'not anymore on files' FROM Staging.Claims AS S WHERE S.ClaimID = C.ClaimID) -- This has to be by the key columns
COMMIT
END TRY
BEGIN CATCH
DECLARE @v_ErrorMessage VARCHAR(MAX) = ERROR_MESSAGE()
IF @@TRANCOUNT > 0
ROLLBACK
RAISERROR (@v_ErrorMessage, 16, 1)
END CATCH
END
这样你总是使用dbo.Claims
并且记录永远不会丢失(只是更新或插入)。
如果您需要检查特定声明的最后状态,可以创建一个视图:
CREATE VIEW dbo.vClaimLastStatus
AS
WITH ClaimsOrdered AS
(
SELECT
C.ClaimAutoID,
C.ClaimID,
C.Name,
C.Status,
C.ModifiedDate,
C.CreatedDate,
DateRanking = ROW_NUMBER() OVER (PARTITION BY C.ClaimID ORDER BY C.CreatedDate DESC)
FROM
dbo.Claims AS C
)
SELECT
C.ClaimAutoID,
C.ClaimID,
C.Name,
C.Status,
C.ModifiedDate,
C.CreatedDate,
FROM
ClaimsOrdered AS C
WHERE
DateRanking = 1