I recently had a horrible blunder.
While attempting to fix an issue we were having with our Exact Synergy system I was attempting to replace the data in two columns for one account with NULL, instead I replaced those two columns in ALL accounts with NULL. Completely restoring from a backup is not an option so now I am left trying to figure out how to replace the missing data.
I have made a full restore of a recent backup for this database to a test database and have confirmed that the data I need is there. I am trying to figure out how to properly write a query that will replace the data in the two columns.
Since this is a backup of the same database, the tables and columns are all identically named.
The databases are Synergy and Synergy_TESTDB
The owner of the tables is dbo
The table is called Addresses
The columns are called textfield1 and textfield2
What I would like to do is take the data in textfield1 and textfield2 from the backup database and use it to populate the empty, or NULL, columns in the live database.
I am extremely new to SQL, and would appreciate any help.
This is obviously untested. I take no responsibility for you using this code.
That said I'd like to try and help you.
The main point is the 3 part database.table naming: I'm assuming you restored backup to same server. I'm also assuming you have a primary key on the table? And that Synergy_TESTDB is the restored database:
update target
set target.textfield1 = source.textfield1
from Synergy.dbo.Addresses target
join Synergy_TESTDB.dbo.Addresses source on target.PrimaryKeyCol = source.PrimaryKeyCol
where target.textfield1 IS NULL
update target
set target.textfield2 = source.textfield2
from Synergy.dbo.Addresses target
join Synergy_TESTDB.dbo.Addresses source on target.PrimaryKeyCol = source.PrimaryKeyCol
where target.textfield2 IS NULL
(Sure it could be done in a single update, but I'm trying to keep it simple.)
I strongly suggest you try in another test database first.
A good habit to get in to is to use a pattern like this:
BEGIN TRANSACTION
-- Perform updates
-- Examine the results: select * from dbo.Blah ...
-- If results are wrong, we just rollback anyway
ROLLBACK
-- If results are what you want, uncomment the COMMIT and comment out the ROLLBACK
-- COMMIT TRANS
In my SQL Server 2012 database, I have a linked server reference to a second SQL Server database that I need to pull records from and update accordingly.
I have the following update statement that I am trying to run:
UPDATE
Linked_Tbl
SET
Transferred = 1
FROM
MyLinkedServer.dbo.MyTable Linked_Tbl
JOIN
MyTable Local_Tbl ON Local_Tbl.LinkedId = Linked_Tbl.Id
JOIN
MyOtherTable Local_Tbl2 ON Local_Tbl.LocalId = Local_Tbl2.LocalId
Which I had to stop after an hour of running as it was still executing.
I've read online and found solutions stating that the best solution is to create a stored procedure on the Linked Server itself to execute the update statement rather than run it over the wire.
The problems I have are:
I don't have the ability to create any procedures on the other server.
Even if I could create that procedure, I would need to pass through all the Ids to the stored procedure for the update and I'm not sure how to do that efficiently with thousands of Ids (this, obviously, is the smaller of the issues, though since I can't create that procedure in the first place).
I'm hoping there are other solutions people may have managed to come up with given that it's often the case you don't have permissions to make changes to a different server.
Any ideas??
I am not sure, whether it can give more performance, you an try:
UPDATE
Linked_Tbl
SET
Transferred = 1
FROM OPENDATASOURCE([MyLinkedServer],'select Id, LocalId,Transferred from remotedb.dbo.MyTable') AS Linked_Tbl
JOIN MyTable Local_Tbl
ON Local_Tbl.LinkedId = Linked_Tbl.Id
JOIN MyOtherTable Local_Tbl2
ON Local_Tbl.LocalId = Local_Tbl2.LocalId
I have a database with multiple tables and I want to log the users activity via my MVC 3 web application.
User X updated category HELLO. Name changed from 'HELLO' to 'Hi There' on 24/04/2011
User Y deleted vehicle Test on 24/04/2011.
User Z updated vehicle Bla. Name changed from 'Blu' to 'Bla' on 24/04/2011.
User Z updated vehicle Bla. Wheels changed from 'WheelsX' to 'WheelsY' on 24/04/2011.
User Z updated vehicle Bla. BuildProgress changed from '20' to '50' on 24/04/2011
My initial idea is to have on all of my actions that have database crud, to add a couple lines of code that would enter those strings in a table.
Is there a better way of checking which table and column has been modified than to check every column one by one with if statements (first I select the current values, then check each of them with the value of the textbox) I did that for another ASPX web app and it was painful.
Now that I'm using MVC and ADO.NET Entity Data Model I'm wondering if a faster way to find the columns that were changed and build a log like the one above.
You can also accomplish this by putting your database into full recovery mode and then reading the transaction log.
When database is in a full recovery mode then sql server logs all Update, insert and delete (and others such as create, alter, drop..) statements into it's transaction log.
So, using this approach you dont need to make any additinal changes to your application or your database structure.
But you will need 3rd party sql transaction log reader. Red gate has a free solution for sql server 2000 only. If your server is 2005 or higher you would probably want to go with ApexSQL Log
Also, this approach will not be able to audit select statements but it's definately the easiest to implement if you dont really need to audit select queries.
The way I see, you have two options:
Create triggers in the database side, mapping changes in a table by table basis and getting result into a Log table
OR
Having the code handle the changes. You would have a base class with data and with reflection you could iterate all object properties and see what has changed. And then save that into your Log table. Of course, that coding would be on your Data Access Layer.
By the way, if you have a good code structure/architecture, I would go with the second option.
You could have a trigger (AFTER insert/update/deelte) on each table you want to monitor. The beauty is columns_updated() which returns a barbinary value, indicating which columns have been updated.
Here is some snippet of code that I put in each trigger:
IF (##ROWCOUNT = 0) return
declare #AuditType_ID int ,
#AuditDate datetime ,
#AuditUserName varchar(128),
#AuditBitMask varbinary(10)
select #AuditDate = getdate() ,
#AuditUserNAme = system_user,
#AuditBitMask = columns_updated()
-- Determine modification type
IF (exists (select 1 from inserted) and exists (select 1 from deleted))
select #AuditType_ID = 2 -- UPDATE
ELSE IF (exists (select * from inserted))
select #AuditType_ID = 1 -- INSERT
ELSE
select #AuditType_ID = 3 -- DELETE
(record this data to your table of choice)
I have a special function that can decode the bitmask values, but for some reason it is not pasting well here. Message me and I'll email it to you.
I've been asked to create a simple DataGrid-style application to edit a single table of a database, and that's easy enough. But part of the request is to create an audit trail of changes made, who made them, and the date/time.
How might you solve this kind of thing?
(I'll be using C# in VS2008, ADO.NET connected to SQL Server 2005, WPF and Xceed's DataGrid, if it makes any difference.)
There are two common ways of creating audit trails.
Code your data access layer.
In the database itself using triggers.
There are advantages and disadvantages to both. Some people prefer one over the other. It's often down to the type of app and the type of database use you can expect.
If you do it in your DA layer it's pretty much up to you. You just need to add code to every method that saves to the database to also save a log of the changes. This auditing code could be in your DA layer code, or even in your stored procs in your database if you are using stored procs for everything. Essentially the premise is the same, any time you make a change to the database, log that change.
If you want to go down the triggers route, you can write custom triggers for each table, or fashion a more generic trigger that works the same on lots of tables. Check out this article on audit triggers. This works by firing of triggers whenever a change is made, and the triggers log the changes. Remember that if you want to audit SELECT statements, you can't use triggers, you'll have to do that with in code/stored proc auditing. It's also worth remember that depending on your database, triggers may not fire in all circumstances. For example, most databases don't fire triggers during TRUNCATE statements. Check that your triggers get fired in any case that you need auditing.
Alternately, you could also take a look at using the service broker to do async auditing on a dedicated machine. This is more complex and takes a bit of configuring to set up.
Which ever way you do it you need to decide on the format the audit log will take. Normally you would save this log in your database, but you could just save it in a log file or whatever suits your requirements. You could use a single audit table that logs all changes, or you could have an audit table per main table being audited. For large scale implementations you could even consider putting the audit tables in a totally separate database. If your logging into a table, it's common to have a "change type" field which indicates if the audited change was an insert, update or delete style of change, along with the changed data, user who made the change and the date/time the change was made. Don't forget to include the old and new data for update style changes.
Ditto use triggers.
Anyone considering soft deletion should have a read of Richard Dingwall's The trouble with soft delete.
Most universal method would be to create another table for storing versions of record from the first table. Then, you can remove all the data from main table. Suppose you need versioning of a table Person(PersonId, Name, Surname):
CREATE TABLE Person
(
PersonId INT, // PK
CurrentPersonVersion INT // FK
);
CREATE TABLE PersonVersion
(
PersonVersionId INT, // PK
PersonID // FK
Name VARCHAR, // actual data
Surname VARCHAR, // actual data
ChangeDate // logging data
ChangeAuthor // logging data
)
Now any change requires inserting new PersonVersion and updating the CurrentPersonVersionID.
The best way to do this is set up triggers in the database that write to audit tables.
Solution 1: SQL Server Change Data Capture
https://learn.microsoft.com/en-us/sql/relational-databases/track-changes/enable-and-disable-change-data-capture-sql-server?view=sql-server-2017
First you need to enable change data capture on your database
USE AdventureWorks2012
GO
EXEC sys.sp_cdc_enable_db
GO
Then you can query the changes using fn_cdc_get_all_changes_ or fn_cdc_get_net_changes_.
-- ========
-- Enumerate All Changes for Valid Range Template
-- ========
USE AdventureWorks2012;
GO
DECLARE #from_lsn binary(10), #to_lsn binary(10);
SET #from_lsn = sys.fn_cdc_get_min_lsn('HR_Department');
SET #to_lsn = sys.fn_cdc_get_max_lsn();
SELECT * FROM cdc.fn_cdc_get_all_changes_HR_Department
(#from_lsn, #to_lsn, N'all');
Solution 2: SQL Server Database Auditing
Source : https://www.dbaservices.com.au/how-to-configure-sql-server-auditing/
ENABLE DATABASE AUDITING
Database auditing requires that a server audit (although not necessarily server audit specification) to be in place. The DB auditing however is created within the user database that is to be audited, rather than within the master database where the server audit gets created. Database audit specifications can be found within the DB itself under Security –> Database Audit Specifications.
To create a database audit, you’ll need to first USE the database (to select it), then the following provides an example syntax for auditing SELECT, UPDATE and DELETE operations for specific tables within that database;
USE UserDatabase
GO
CREATE DATABASE AUDIT SPECIFICATION [User_Database_Audit_Specification]
FOR SERVER AUDIT [SQL_Server_Audit]
ADD (SELECT , UPDATE , DELETE ON UserDatabase.dbo.Customer_DeliveryAddress BY dbo )
,ADD (SELECT , UPDATE , DELETE ON UserDatabase.dbo.DimCustomer_Email BY dbo )
,ADD (SELECT , UPDATE , DELETE ON UserDatabase.dbo.DimCustomer_Phone BY dbo )
WITH (STATE = ON) ;
GO
The SELECT, UPDATE and DELETE operations aren’t the only things you can add to the audit specification though…
+------------+-------------------------------------------------------------------+
| Action | Description |
+------------+-------------------------------------------------------------------+
| SELECT | This event is raised whenever a SELECT is issued. |
| UPDATE | This event is raised whenever an UPDATE is issued. |
| INSERT | This event is raised whenever an INSERT is issued. |
| DELETE | This event is raised whenever a DELETE is issued. |
| EXECUTE | This event is raised whenever an EXECUTE is issued. |
| RECEIVE | This event is raised whenever a RECEIVE is issued. |
| REFERENCES | This event is raised whenever a REFERENCES permission is checked. |
+------------+-------------------------------------------------------------------+
The full list of database events you can log is available here:
https://learn.microsoft.com/en-us/sql/relational-databases/event-classes/security-audit-event-category-sql-server-profiler?view=sql-server-2017
I was recently faced with a requirement to audit some tables and I opted to use triggers. Like others, I only wanted to see entries in the audit table for those fields that had actually changed, however, when updating the tables, the application was updating all the fields in row whether they'd changed or not, therefore, checking whether the fields had been updated or not availed me nothing - they all had!
What I wanted, therefore, was a method of checking the actual value in each field to see if it had changed or not and only writing it to the audit table if it had. Having been unable to find any solution to this conundrum anywhere, I came up with my own, as follows:
CREATE TRIGGER [dbo].[MyTable_CREATE_AUDIT]
ON [dbo].[MyTable]
AFTER UPDATE
AS
INSERT INTO MyTable_Audit
(ItemID,LastModifiedBy,LastModifiedDate,field1,field2,field3,
field4,field5,AuditDate)
SELECT i.ItemID,i.LastModifiedBy,i.LastModifiedDate,
field1 =
CASE i.field1
WHEN d.field1 THEN NULL
ELSE i.field1
END,
field2 =
CASE i.field2
WHEN d.field2 THEN NULL
ELSE i.field2
END,
field3 =
CASE i.field3
WHEN d.field3 THEN NULL
ELSE i.field3
END,
field4 =
CASE i.field4
WHEN d.field4 THEN NULL
ELSE i.field4
END,
field5 =
CASE i.field5
WHEN d.field5 THEN NULL
ELSE i.field5
END,
GETDATE()
FROM inserted i
INNER JOIN deleted d
ON i.ItemID = d.ItemID
As you can see, I'm comparing the values of each field in the deleted and inserted tables and only writing the field value from the inserted table to the audit table if they differ, otherwise I just write NULL.
It certainly works for me. Can anyone see any issues with this approach? My team own both the application and the database so possible curved balls like schema changes are covered off.
The other way of doing this apart from triggers is this,
Have four columns, UpdFlag, DelFlag, EffectiveDate and TerminatedDate for each table you want to do an audit trail on.
code your sproc's in such a way that when you do an update, to pass in the all of the row's column data into the sproc, update the row by setting the TerminatedDate to the date that was updated, and mark the UpdFlag and to put in the datetime into the column
Then create a new row with the new data (which is really updated). and put in a new date now for the EffectiveDate and the TerminatedDate set to the max date.
Likewise if you want to do a deletion of the row, simply update the row by marking the DelFlag as set, the TerminatedDate with the datetime now. You are in effect doing a soft delete and not an actual sql's Delete.
In that way, when you want to audit the data, and to show a trail of the changes, you can simply filter the rows for those that have the UpdFlag set, or between EffectiveDate and TerminatedDate. Likewise for those that were deleted, you filter for those that have the DelFlag set or between EffectiveDate and TerminatedDate. For the current rows, filter the rows that have both flags set off. The advantage is you don't have to create another table for the audit when the trigger is used!
I'd go triggers route, by creating table with similar structure to updated one, with additional columns for tracking changes like ModifiedAt etc. And then adding on update trigger that will insert changes to that table.
I find it easier to maintain than have everything in the application code. Ofcourse many people tend to forget about triggers when it comes to questions like 'wtf this table is changing' ;) Cheers.
Suppose I had a table with a large number of records, I wanted to update all the record in that table using SQL Server managment studio 2008, I typed:
Update Table set col1 = val
It will take a while for this command to update all the records, now if I pressed stop excutioin, what exactly will happen, some records will be upodated and committed or non like I've never excuted that command?
it will be all or nothing, it is a set based operation
SQL Server uses implicit transaction if an explicit one has not been started, this is a way to ensure ACID
so to answer your question if you stop it it will be in the same state as it was before you pressed ! or F5