如何在运行时查找受存储过程影响的表和列名称?

时间:2015-03-04 08:29:46

标签: sql sql-server sql-server-2008 stored-procedures

假设我的逻辑中有if else条件的存储过程。如果条件为真,则表示更新tableA,否则更新tableB。我希望获得受其所有列影响的表名,其值根据运行存储过程时发生的条件执行而更新。

这用于记录目的,即哪个表,列受哪个存储过程以及由谁影响。 我正在使用SQL Server 2008.如果您有任何建议可以告诉我。

3 个答案:

答案 0 :(得分:0)

有许多不同的记录方法,但一种方法是使用触发器。请参阅SQL Server联机文档中的DML Triggers。创建一个日志表,然后在TableA和TableB上创建一个AFTER TRIGGER,将适当的信息写入日志表。

答案 1 :(得分:0)

行级&列级跟踪

更改跟踪使应用程序能够跟踪用户所做的所有更改,这是一种内置方法

enter link description here

SQL Server更改跟踪确定列是否已更改,因此我决定使用下面的脚本在2008 R2中尝试更改。基本上在最后一个更新语句中,我将列更新为列中已存在的相同值。 SQL似乎只记录该列涉及更新语句。不幸的是,这意味着任何希望在列级执行同步操作的人都必须编写更复杂的行更新逻辑。

CREATE TABLE [dbo].[Test]( 
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [A] [varchar](50) NULL, 
    [B] [int] NULL 
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
( 
    [Id] ASC 
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY] 
) ON [PRIMARY]

GO

ALTER DATABASE TrackingTest 
SET CHANGE_TRACKING = ON 
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON)

ALTER TABLE TrackingTest.dbo.Test 
ENABLE CHANGE_TRACKING 
WITH (TRACK_COLUMNS_UPDATED = ON);

GO

INSERT INTO dbo.Test (A,B) VALUES ('C', 50) 
INSERT INTO dbo.Test (A,B) VALUES ('D', 50)

SELECT 'SYS_CHANGE_COLUMS = NULL means that all columns changed.' 
SELECT 
    CT.Id, CT.SYS_CHANGE_OPERATION, 
    CT.SYS_CHANGE_COLUMNS, CT.SYS_CHANGE_CONTEXT, 
    CHANGE_TRACKING_IS_COLUMN_IN_MASK (COLUMNPROPERTY(OBJECT_ID('dbo.Test'), 'A', 'ColumnId'),CT.SYS_CHANGE_COLUMNS) AS A_CHANGED, 
    CHANGE_TRACKING_IS_COLUMN_IN_MASK (COLUMNPROPERTY(OBJECT_ID('dbo.Test'), 'B', 'ColumnId'),CT.SYS_CHANGE_COLUMNS) AS B_CHANGED 
FROM 
    CHANGETABLE(CHANGES dbo.Test, NULL) AS CT

DECLARE @synchronization_version BIGINT 
SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();

SELECT * FROM dbo.Test 
SELECT 'Changing both columns via "UPDATE dbo.Test SET A=''E'', B=51"' 
UPDATE dbo.Test SET A='E', B=51 
SELECT * FROM dbo.Test

SELECT 
    CT.Id, CT.SYS_CHANGE_OPERATION, 
    CT.SYS_CHANGE_COLUMNS, CT.SYS_CHANGE_CONTEXT, 
    CHANGE_TRACKING_IS_COLUMN_IN_MASK (COLUMNPROPERTY(OBJECT_ID('dbo.Test'), 'A', 'ColumnId'),CT.SYS_CHANGE_COLUMNS) AS A_CHANGED, 
    CHANGE_TRACKING_IS_COLUMN_IN_MASK (COLUMNPROPERTY(OBJECT_ID('dbo.Test'), 'B', 'ColumnId'),CT.SYS_CHANGE_COLUMNS) AS B_CHANGED 
FROM 
    CHANGETABLE(CHANGES dbo.Test, @synchronization_version) AS CT

SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();

SELECT * FROM dbo.Test 
SELECT 'Only setting column A to the value already in the column via "UPDATE dbo.Test SET A=''E''"' 
UPDATE dbo.Test SET A='E' 
SELECT * FROM dbo.Test

SELECT 'Now SYS_CHANGE_COLUMS has a value showing that only A was changed' 
SELECT 'To bad it isn''t smart enough to know that the data did not change!'

SELECT 
    CT.Id, CT.SYS_CHANGE_OPERATION, 
    CT.SYS_CHANGE_COLUMNS, CT.SYS_CHANGE_CONTEXT, 
    CHANGE_TRACKING_IS_COLUMN_IN_MASK (COLUMNPROPERTY(OBJECT_ID('dbo.Test'), 'A', 'ColumnId'),CT.SYS_CHANGE_COLUMNS) AS A_CHANGED, 
    CHANGE_TRACKING_IS_COLUMN_IN_MASK (COLUMNPROPERTY(OBJECT_ID('dbo.Test'), 'B', 'ColumnId'),CT.SYS_CHANGE_COLUMNS) AS B_CHANGED 
FROM 
    CHANGETABLE(CHANGES dbo.Test, @synchronization_version) AS CT 

Results are:

enter image description here

答案 2 :(得分:0)

您需要在UPDATE triggersTableA上创建TableB。以下是语法:

CREATE TRIGGER TriggerName
    ON [dbo].[TableName]
    FOR UPDATE
    AS
    BEGIN
    SET NOCOUNT ON
    -- here goes your code
    -- you can select updated values by following
    SELECT *
    FROM
      inserted
    INNER JOIN
      deleted
        ON inserted.PrimaryKey = deleted.PrimaryKey
        -- Update is detected when is in both: deleted and inserted
    END

<强>更新

因此,您可以从存储过程中选择更新的数据,并将其插入临时表。

CREATE PROCEDURE sp_example
@var1 INT,
@var2 NVARCHAR(40),
@var3 NVARCHAR(60)
AS
BEGIN
   INSERT INTO ExampleTbl VALUES (@var1, @var2, @var3)
   -- You could create temp table as shown below
   CREATE TABLE #TempTbl
   (
      Id INT,
      Name NVARCHAR(40),
      Email NVARCHAR(60),
   )
   INSERT INTO #TempTbl VALUES (@var1, @var2, @var3)   
   SELECT * FROM #TempTbl
END