For my company, we have made it a standard to create history tables and triggers for the majority of our production tables. I recently grew tired of consistently spending the time needed to create these tables and triggers so I invested some time in creating a script that would auto generate these.
We recently launched a project which required nearly 100 history tables & triggers to be created. This would have normally taken a good day or two to complete. However, with this script it took a near 10 seconds. Here are some details about the script.
The code below creates a stored procedure that receives two input parameters (@TableName & @CreateTrigger) and performs the following actions:
1) Queries system tables to retrieve table schema for @TableName parameter
2) Creates a History table ("History_" + @TableName) to mimic the original table, plus includes additional history columns.
3) If @CreateTrigger = 'Y' then it creates an Update/Delete trigger on the @TableName table, which is used to populate the History table.
/************************************************************************************************************
Created By: Bryan Massey
Created On: 3/11/2007
Comments: Stored proc performs the following actions:
1) Queries system tables to retrieve table schema for @TableName parameter
2) Creates a History table ("History_" + @TableName) to mimic the original table, plus include
additional history columns.
3) If @CreateTrigger = 'Y' then it creates an Update/Delete trigger on the @TableName table,
which is used to populate the History table.
******************************************* MODIFICATIONS **************************************************
MM/DD/YYYY - Modified By - Description of Changes
************************************************************************************************************/
CREATE PROCEDURE DBO.History_Bat_AutoGenerateHistoryTableAndTrigger
@TableName VARCHAR(200),
@CreateTrigger CHAR(1) = 'Y' -- optional parameter; defaults to "Y"
AS
-- query system tables to get table schema
SELECT CONVERT(VARCHAR(500), SP2.value) AS TableDescription,
CONVERT(VARCHAR(100), SC.Name) AS FieldName, CONVERT(VARCHAR(50), ST.Name) AS DataType,
CONVERT(VARCHAR(10),SC.length) AS FieldLength, CONVERT(VARCHAR(10), SC.XPrec) AS FieldPrecision,
CONVERT(VARCHAR(10), SC.XScale) AS FieldScale,
CASE SC.IsNullable WHEN 1 THEN 'Y' ELSE 'N' END AS AllowNulls
FROM SysObjects SO
INNER JOIN SysColumns SC ON SO.ID = SC.ID
INNER JOIN SysTypes ST ON SC.xtype = ST.xtype
LEFT OUTER JOIN SysProperties SP ON SC.ID = SP.ID AND SC.ColID = SP.SmallID
LEFT OUTER JOIN SysProperties SP2 ON SC.ID = SP2.ID AND SP2.SmallID = 0
WHERE SO.xtype = 'u' AND SO.Name = @TableName
ORDER BY SO.[name], SC.ColOrder
OPEN CurHistoryTable
FETCH NEXT FROM CurHistoryTable INTO @TableDescr, @FieldName, @DataType,
@FieldLength, @Precision, @Scale, @AllowNulls
WHILE @@FETCH_STATUS = 0
BEGIN
-- create list of table columns
IF LEN(@FieldList) = 0
BEGIN
SET @FieldList = @FieldName
SET @FirstField = @FieldName
END
ELSE
BEGIN
SET @FieldList = @FieldList + ', ' + @FieldName
END
IF LEN(@SQLTable) = 0
BEGIN
SET @SQLTable = 'CREATE TABLE [DBO].[History_' + @TableName + '] (' + @CRLF
SET @SQLTable = @SQLTable + @TAB + '[History' + @FieldName + '] [INT] IDENTITY(1,1) NOT NULL,' + @CRLF
END
IF UPPER(@DataType) IN ('CHAR', 'VARCHAR', 'NCHAR', 'NVARCHAR', 'BINARY')
BEGIN
SET @SQLTable = @SQLTable + '(' + @FieldLength + ')'
END
ELSE IF UPPER(@DataType) IN ('DECIMAL', 'NUMERIC')
BEGIN
SET @SQLTable = @SQLTable + '(' + @Precision + ', ' + @Scale + ')'
END
IF @AllowNulls = 'Y'
BEGIN
SET @SQLTable = @SQLTable + ' NULL'
END
ELSE
BEGIN
SET @SQLTable = @SQLTable + ' NOT NULL'
END
SET @SQLTable = @SQLTable + ',' + @CRLF
FETCH NEXT FROM CurHistoryTable INTO @TableDescr, @FieldName, @DataType,
@FieldLength, @Precision, @Scale, @AllowNulls
END
CLOSE CurHistoryTable
DEALLOCATE CurHistoryTable
-- finish history table script with standard history columns
SET @SQLTable = @SQLTable + @TAB + '[HistoryCreatedOn] [DATETIME] NULL,' + @CRLF
SET @SQLTable = @SQLTable + @TAB + '[HistoryCreatedByUserID] [SMALLINT] NULL,' + @CRLF
SET @SQLTable = @SQLTable + @TAB + '[HistoryCreatedByUserName] [VARCHAR](30) NULL,' + @CRLF
SET @SQLTable = @SQLTable + @TAB + '[HistoryAction] [CHAR](1) NOT NULL' + @CRLF
SET @SQLTable = @SQLTable + ' )'
PRINT @SQLTable
-- execute sql script to create history table
EXEC(@SQLTable)
IF @@ERROR <> 0
BEGIN
PRINT '******************** ERROR CREATING HISTORY TABLE FOR TABLE: ' + @TableName + ' **************************************'
RETURN -1
END
IF @CreateTrigger = 'Y'
BEGIN
-- create history trigger
SET @SQLTrigger = '/************************************************************************************************************' + @CRLF
SET @SQLTrigger = @SQLTrigger + 'Created By: ' + SUSER_SNAME() + @CRLF
SET @SQLTrigger = @SQLTrigger + 'Created On: ' + @Date + @CRLF
SET @SQLTrigger = @SQLTrigger + 'Comments: Auto generated trigger' + @CRLF
SET @SQLTrigger = @SQLTrigger + '***********************************************************************************************/' + @CRLF
SET @SQLTrigger = @SQLTrigger + 'CREATE TRIGGER [Trigger_' + @TableName + '_UpdateDelete] ON DBO.' + @TableName + @CRLF
SET @SQLTrigger = @SQLTrigger + 'FOR UPDATE, DELETE' + @CRLF
SET @SQLTrigger = @SQLTrigger + 'AS' + @CRLF + @CRLF
SET @SQLTrigger = @SQLTrigger + 'DECLARE @Action CHAR(1)' + @CRLF + @CRLF
SET @SQLTrigger = @SQLTrigger + 'IF EXISTS (SELECT ' + @FirstField + ' FROM Inserted)' + @CRLF
SET @SQLTrigger = @SQLTrigger + 'BEGIN' + @CRLF
SET @SQLTrigger = @SQLTrigger + @TAB + 'SET @Action = ''U''' + @CRLF
SET @SQLTrigger = @SQLTrigger + 'END' + @CRLF
SET @SQLTrigger = @SQLTrigger + 'ELSE' + @CRLF
SET @SQLTrigger = @SQLTrigger + 'BEGIN' + @CRLF
SET @SQLTrigger = @SQLTrigger + @TAB + 'SET @Action = ''D''' + @CRLF
SET @SQLTrigger = @SQLTrigger + 'END' + @CRLF + @CRLF
SET @SQLTrigger = @SQLTrigger + 'INSERT INTO History_' + @TableName + @CRLF
SET @SQLTrigger = @SQLTrigger + @TAB + '(' + @FieldList + ', HistoryCreatedOn, HistoryCreatedByUserName, HistoryAction)' + @CRLF
SET @SQLTrigger = @SQLTrigger + 'SELECT ' + @FieldList + ', GETDATE(), SUSER_SNAME(), @Action' + @CRLF
SET @SQLTrigger = @SQLTrigger + 'FROM DELETED'
--PRINT @SQLTrigger
-- execute sql script to create update/delete trigger
EXEC(@SQLTrigger)
IF @@ERROR <> 0
BEGIN
PRINT '******************** ERROR CREATING HISTORY TRIGGER FOR TABLE: ' + @TableName + ' **************************************'
RETURN -1
END
I have to create a history of tables. Therefore I must know the previous structure of the table. I have to document the changes of the structures of the tables. Is there a solution for the version 2000?
HiI am looking to implement an audit/history table/tables but am lookingat doing this without the use of triggers.The reason for doing this is that the application is highlytransactional and speed in critical areas is important.I am worried that triggers would slow things down.I am more used to other database where by there is a utility to "dump"the contents of the transaction logs and use this for auditingpurposes. However SQL Server does not have this functionality (unlessthere is a sql server tool - 3rd party that I do not know about)Has anyone implemented something similar? Or used/using a 3rd partytool that will do this job.Effectively the clients would like to "look" at what happened - say 15minutes ago.thanksjohn
Hello. Taking a typical use having a history table, maintained from a base table via triggers... Trying to see how/if that can be done using the SQl 2005 Service Broker method, with messaging? The thought is that if we can do the History table updates ASYNC, the user will not wait more than setting up the Broker message queue. I saw this article about something similar, but it deals with LOGON triggers.
I'd think you can't do Hisotyr type triggers, with a message, because wouldn't you need to write all teh INSERTED/UPDATED data somewhere anyways? and there could be multiple rows affected in any given insert/update/delete, so could you even pass that thru to a Broker?
Anyone know of any references to using Broker Services for sending INSERTED/UPDATED data along for Historical versioning?
Also, was curious about error handling, because say you update teh base table, and then a problem occurs, and the Hisotry table is not updated. I want them in sync. Where is the message data stored, and is it accesible even if teh server reboots before the data is RECEIVED from teh QUEUE?
How can we programmatically cause a Manual Report History Snapshot to be created.
I know it can be done using the Webservice. How would we do it using the ReportServer stored procedures. Which SP/SP's can we call. With what parameters.
I want to backup an important table every week in creating some history tables.
I would like to create a Dts job or script to create every week a table with the day and month in its name. ( like : [important_table_09-07] , [important_table_09-14],... )
When creating history tables that are appended to whenever a record isupdated, should one append the corresponding child table records to theirhistory tables at the same time (so as to have a complete set for eachedit); or should one append the child tables only when those particulartables are edited? I have been doing the latter, but I thought I'd ask forothers' opinions.Thanks!Neil
I've got a large and growing database in SQL Server 7.0. I'd like to utilize a monthly stored procedure that will search various tables for records that are older than 3 months and copy this data out to corresponding history tables. Typically, most production queries are run only on the new data, but occasionally (like at year-end, for example), we will need to run some queries on data extending back 12 months -- that is, on data in the production tables AND in the history tables. Notwithstanding the fact that I've never done stored procedures*, I would like to know if it is possible to run a query that can search for data in both production and history tables at the same time. I know this sounds like a stupid question, but I read somewhere that doing this qould require some kind of Joining function that is complex...?
Thanks, Whill96205
* Also, any good resources I could use for developing stored procedures?
We have a need to report on historical data when none exists in the database.
Create a tabular report rdl that is run on a regular schedule. This report run is saved as an Excel sheet that overwrites the previous run, which has the same name.
Report is designed to use two data sources--the database and and the previously run Excel sheet. The data is "merged" using the Lookup function thereby creating a new report that includes the history needed.
I created a table with a field called myID. I set the data type as "uniqueidentifier", but it won't auto generate. How do I create a field to auto generate a unique number? I'm working with SQL Server 2000 and I'm creating the table from Enterprise Manager.
hy guys i m trying to create trigger but i tired to get an error msg
trigger which i want to create is :
CREATE TRIGGER TR_TESTING ON EMPLOYEES FOR INSERT AS DECLARE @TMP AS VARCHAR(1) SET @TMP=SUBSTRING(FirstName,0,1) FROM EMPLOYEES IF @TMP='A' BEGIN INSERT INTO EMPLOYEES(LastName,FirstName) VALUES('DHARANI','AAMIR') END ELSE BEGIN PRINT 'INSERT VALID RECORD' END
Hi Guys, Is there any Wizard or software or tools that I can use to create Triggers for my tables ... !???? It is for MSSQL 2005 database Thanks for your help,Mehdi
Would it be possible to generate SQL Script using triggers or stored procedures whenever there is a change in database tables like UPDATE or APPEND. Whenever we update or append record it should create a script and save it in a text file so that we can update parent database only with those updated records.
Hi does anyone know how to create a sql table and then import a list by just clicking on a button to call a procedure?CREATE TABLE clients(ClientID VARCHAR(5), ClientName VARCHAR(30), PRIMARY KEY (ClientID));LOAD DATA LOCAL INFILE 'C:/client.csv' INTO TABLE clientsLINES TERMINATED BY ' ';
I know that statistics called _WA_... are created on tables when auto create statistics is set on a database. Is this an indication that queries against the table would perform better if indexes were created on the columns in question? (The tables I'm interested in optimising are used equally for transactional querying and reporting)
Hi,I'm a newbie to sql server and this may be a really dumb question forsome you. I'm trying to find some examples of sql server triggers thatwill set columns (e.g. the created and modified date columns) if the rowis being inserted and set a column (e.g. just the modified date column)if the row is being updated.I know how to do this in oracle plsql. I would define it as a beforeinsert or update trigger and reference old and new instances of therecord. Does sql server have an equivalent? Is there a better way to dothis in sql server?Thanksericthis is what i do in oracle that i'm trying to do in sqlserver...CREATE OR REPLACE TRIGGER tr_temp_biubefore insert or updateon tempreferencing old as old new as newfor each rowbeginif inserting then:new.created_date := sysdate;end if;:new.modified_date := sysdate;end tr_temp_biu;
Hello, everyone. I am sorry I haven't been around for long but I have got this confusion. I haven't been able to set triggers between 2 tables.
I have got a set of data in 1 table and another set in the other table. I want to set the trigger by comparing the data column from one table to another.
All I want to know is is ti possible to do it? Because I have been told that I can only set triggers on only one table.
I have been working on a Human Resource Management software in C# .NET. In its Employee Attendance module i need to keep records of attendance of all workers for one month in a single table.The problem I encounter is to auto generate an exact copy of the Attendance table after a particular month is finished. How can i accomplish this? I use SQL server 2008.
I'm thinking of building a trigger against a system table(sysobjects) in database(a) on server(a) that will assist me in updating a table in database(b)on server(b). What I need to know from table(b)is if a new table has been added and removed from database(a) on server(a). I want to use a store procedure to query the table(b). I was thinking of building a trigger against my sysobjects table that would update table(b) whenever any tables are added or removed from database(a). Has anyone built triggers against system tables? I am running SQL 7.
Dear Group,I would like to create an audit table that is created with a trigger thatreflects all the changes(insert, update and delete) that occur in table.Say I have a table withSubject_ID, visit_number, dob, weight, height, User_name, inputdateThe audit table would have .Subject_ID, visit_number, dob, weight, height, User_name, inputdate,edit_action, edit_reason.Where the edit_action would be insert, update, delete; the edit_reason wouldbe the reason given for the edit.Help with this would be great, since I am new to the world of triggers.Thanks,Jeff
I have decided to use CLR Triggers to synchronize data between two different tables but I have a problem. The scenario is this. I do an insert in Table1. Table1 firest the trigger which then inserts a record in Table2. The trigger in Table2 fires a trigger which does an insert to Table1 again.
I need to find a way to disable the trigger so that it will not go in an infinite loop when I insert a record in either of the tables. What I have done so far is to disable Table2's trigger before I commit my insert to Table2 so that Table2's trigger won't fie. I will then enable the trigger after the insert is committed. Also, I have a webservice which manages the inserts/updates/deletes. I call webmethods from this webservice in my clr triggers.
I'm changing data storage for an asp.net project from MS Access to Sql Server. I've got the web site working, but I need to update the sql server tables with data from our Oracle db daily. What is the "best" way to do that?
I've read about DTS, but have never done anything like that. Would it be worth the time and effort to study? (So far I've created a package, with the import wizard, that doesn't work & I don't have the authority to delete :-)
I know I could create a dataset with my Oracle data and use that to update sql server. But is there a way to schedule an aspx to run authomatically? Would this affect performance? The sql server db isn't very big (30-40,000 records), but the Oracle db is & I need to do quite a bit of manipulation to the data.
This is new to me & I'm don't know what I should be searching for to find help. And if there is a more appropriate place to post this question, please let me know.
How can we write triggers on system table dbo.sysobjects, when i tries to write a trigger, it is giving an error that permission is denied. I even give a permission of "allow modifications to system catalogs" in Enterprise manager. still it is not giving permission. How can i create a trigger on dbo.sysobjects table?