Change Data Capture's unexpected behaviour when altering the table - sql-server

I'm using CDC feature from SQL Server 2019.
I understand that if I make any DDL changes to the tracked table the changes info will be added to [cdc].[ddl_history] table, but the changes will not reflect in the existing capture instance.
But in my case the following two things happening.
If I make changes to a key column after cdc is enabled, for eg. set IDENTITY Yes to No or vice versa, the cdc is straightaway disabled
automatically and I lost all the capture information.
If I add new columns and delete existing data from the table, it is disabling cdc automatically without adding DDL changes to ddl_history
tables.
Due to this issue the existing jobs failing and creating a big mess of the whole process. please can someone help me on how to deal with this unexpected behaviour. I have gone through most of the documentation on cdc topic from ms documentation. I didn't come across the automatic disabling of cdc on a table, or I must have missed.
Thanks for looking at my query.
UPDATE: I'm making the changes in SSMS, in table designer.
For IDENTITY: Select column properties and then under Identity Specification set IsIdentity to Yes/No.
For New columns: Add new columns in the designer. Not using ALTER TABLE script (Not sure if it makes a difference to cdc)

Related

Get tablename at the start of event trigger in PostgreSQL

I am looking for the possibility to capture the name of a table on CREATE TABLE, DROP TABLE and other operations in my postgres database.
I looked into event triggers and they seem to only be able to capture these events on ddl_command_end (https://www.postgresql.org/docs/current/functions-event-triggers.html#PG-EVENT-TRIGGER-SQL-DROP-FUNCTIONS), which should work for the CREATE case but not all of the others.
So I wanted to ask, if there exists a possibility to either get the data from a dropped table (as I would need it) or get the information before the event happens.
Thank you for your help!
In Oracle we have a option to recover table but in PostgreSQL we do not have that option. Only thing you can do for this kind of situation enabling archiving and following PITR steps. It could be on other server or on the server that your database running. It depends on significance of the dropped table and the database.

Is this an appropriate database design if I wanted to audit my table?

It's my first time creating an audit log for a PoS WPF application and was wondering on how exactly do I implement an auditing system because it seems like each option available has its ups and downs. So far from reading numerous articles/threads, I've narrowed down a few common practices on audit logs:
1. Triggers - Unfortunately, due to the nature of my app, I can't make use of triggers as it has no way of knowing which user has done the action. So what I did instead was to create a Stored Procedure which will handle the customer insert along with the customer log insert and its details. The Customer_Id will be provided by the application when using the Stored Procedure.
2. Have an old and new value - My initial plan was to only include the latter since I can reference its old value with the new value from the row before it but storing the the old and new value seemed more sensible, complexity-wise.
3. Use a separate database for the log / 4. Foreign Keys - This is probably my main concern, if I decide to use a separate database for the audit table, then I couldn't setup foreign keys for the customer and employee involved.
I created a mock-up erd with a master-detail table result to be shown on the wpf app to display the log to an admin and would really like your thoughts on possible problems that may arise (There's also an employee table but I forgot to put it):
https://ibb.co/dheaNK
Here's a few info that might be of help:
The database will reside together with the wpf app, which is a single computer.
The amount of customers will be less than 1000.
The amount of regular employees will be 3.
The amount of admins will be 2.
You can enable CDC Change Data Capture on SQL Server database for a specific table
This will enable you to collect all data changes on the database table logged in special tables.
You can also refer to official documents too
Here is a list of DML commands and how data changes are logged in the CDC table created for the source database table
What is good about CDC is it comes default with SQL Server and you don't have to do anything for logging. The only requirement is SQL Server Agent should be running so that the changes can be reflected on log table.

Message: This row was successfully committed to the database. However, a problem occurred

I have a table in SQL Server 2005 whose primary key is an identity column (increment 1), and I also have a default value set for one of the other columns.
When I open the table in SQL Server Management Studio and type in a new record into the table, the inserted values are not displayed, and I get the following message on save:
However, if the table has either an identity column, or one or more columns with a default value specified, the inserted value(s) will be displayed in the table after a save. And can be edited.
I frequently create test data in ssms this way and this issue makes it cumbersome to do some things I would like to.
Is there any way around this?
Right click on it and say Execute SQL...it should not display it(error)..its just sql server way of doing things..since it inserts the identity column later..You should not add records in that way in the first place.
You should not add records to a database that way! It can have unfortunate side effects (especially on large tables) as you have discovered.
Records for lookup tables should be added through rerunable scripts. Those scripts should in source control. This makes them easy to promote from dev to Qa to staging to prod.
Test records should also be done in scripts (including scripts to remove the test records) so that you can run thenm on other environments as well as being able to delete and recreate them if some process you are testing went bad. These too should eb in source control (as should all database changes which also should not be done through the GUI).

How to make a log on relational-data in SQL-Server?

I need to create in my DB a log, that every action in the program should be written there.
I will also want to store additional data to it for example have the table and row the action was applied to.
In other words I want the log to be dynamic and should be able to refer to the other tables in the database.
The problem is, I don't know how to relate all the tables to this log.
Any ideas?
You have two choices here:
1) modify your program to add logging for every db access
2) add triggers to each table in your db to perform logging operations.
I don't recommend one logging table for all tables. You will have locking issues if you do that (every insert, update and delete in every table woudl have to hit this one, bad idea). Create a table for each table that you want to audit. There are lots of possible designs for the table, but they usually include some variant of old vlaue, new value, date changed, and user who did the change.
Then create triggers on each table to log the changes.
I know SQL Server 2008 also has a systemic way to set up auditing, this would be easier to set up than manual auditing and might be enough to lure your company into using 2008.

Get database name from DDL Trigger

I am creating a server level trigger in SQL 2008 to log table creation and drops. I need to log the database that the table was created in/dropped from. First I created a column with a default value of db_name(), but this always recorded master. Next I tried using this in my insert statement:
EVENTDATA().value('(/EVENT_INSTANCE/DatabaseName)[1]','nvarchar(max)')
This worked for a while, but suddenly it started recording master for all table creations and drops regardless of the database the table was in. All of the table drops have been done using SSMS. Does anyone know why I am seeing this behavior? Even more important, does anyone know how to log the correct database?
EDIT: I found an article which makes me think what I'm doing is incorrect. Apparently you should only capture create_table and drop_table from a database scoped trigger and not from a server_scoped trigger. I would still like to leave the question open though in case someone knows how to work around this.
HI,
You are correct, CREATE TABLE and DROP TABLE events should be recorded from within DDL Triggers that are defined at the database level.
Server Level Triggers are intended for server wide events, for example, when a Login occurs.
Here is an excellent article that may assist you in your developments.
http://www.developer.com/db/article.php/3552096
The following refence details which DDL events can be fired at either Database or Server scope.
http://msdn.microsoft.com/en-us/library/ms189871(SQL.90).aspx
Cheers,

Resources