Trigger to capture schema changes in the Server - sql

Is it possible to implement something like the following trigger
CREATE TRIGGER [tr_AU_ddl_All_Server] ON DATABASE
WITH EXECUTE AS self
FOR DDL_DATABASE_LEVEL_EVENTS
AS
DECLARE
#data XML
, #rc INT
SET #data = EVENTDATA()
EXEC #rc = __AU.dbo.AU_DDLLog #data
GO
BUT on the whole server. My idea is to capture all schema changes across all the databases in the server.
As far as im concerned this is not possible in SQL Server 2005, but I'd like to know if anyone got something like this to work. I'd like to avoid having to implement a trigger in every single database.

Yes, SQL Server 2005 introducted the "DDL Triggers" - read an excellent article on it here at SQL Team.
This article shows nicely that they are two scopes for DDL triggers - server-wide, or database-wide. Those that are database-wide cannot be applied to the whole server - you'd have to set them up in each database.
Marc

Related

Validating a Dynamic SQL DELETE statement without executing the statement [duplicate]

I have access to an Access database and within that database are fields filled with TSQL queries. These queries are processed by T-SQL on a server. So when I write these SQL queries and put them into a field for use by the end server, I'm unable to validate the syntax/etc. I could create a temporary query in that Access database, but it's not the same query language. For example, Access would correctly use IIF but TSQL would not (it would instead be CASE).
I don't have direct access to this server with TSQL, is there a way I can validate my T-SQL queries (for syntax and the like)? Perhaps a web tool online?
I should note I do not have access to the SQL server. Only the Access db and that alone. I understand it will not validate table names and the like, I wouldn't expect it to.
Actually, a combination of MattMc3's answer and FremenFreedom's answer should work.
Download SQL Express.
Then, declare the following stored procedure:
create procedure IsValidSQL (#sql varchar(max)) as
begin
begin try
set #sql = 'set parseonly on;'+#sql;
exec(#sql);
end try
begin catch
return(1);
end catch;
return(0);
end; -- IsValidSQL
You can test it with:
declare #retval int;
exec #retval = IsValidSQL 'select iif(val, 0, 1) from t';
select #retval
or with:
declare #retval int;
exec #retval = IsValidSQL 'select val from t';
select #retval
Note: this will catch the IIF() issue. It will not catch anything related to the table structures or column structures. You would need the schema for that and a slightly different approach ("select top 0 * from () t") woudl do it.
You might be able to do something with SQL Fiddle online. However, I would suggest having a local copy of the database.
You can parse your T-SQL to check for valid syntax by executing it on the SQL Server machine with a SET PARSEONLY ON as the first line of your script. It will not validate table or field names, but will provide you with any syntax errors.
The Data Dude (Gert Drapers) describes how to use the built-in SQL Server T-SQL parser in your application here:
Getting to the Crown Jewels
If you want to only check the validity of the SQL statements that you have - this might be a nice way to go, and it doesn't require SQL Server per se to be installed where you run your unit tests.
It's a .NET based approach, and it cannot - of course - validate object names in your database if you're not using a live database - but it can catch syntactical errors in your T-SQL statements.
You can use the NOEXEC option:
SET NOEXEC ON
SELECT 1 AS Test
SET NOEXEC OFF
Is SQL Server Management Studio Express (free download) able to connect to regular SQL Server instances? If so, perhaps you could test the queries there. Even if you could not connect to the actual server, you might be able to create a test version of your database in Express that would at least allow you to catch syntax and naming problems.
If they are fairly static, convert them into stored procedures in the Sql Database and then just call them from access.

creating a trigger that updates row in a linked mysql server

i created a linked Mysql server on SQL server 2008 r2. i'm trying to create a trigger on sql table that automatically updates a field in the linked server table, i have a table called "QFORCHOICE" in sql that has fields "Prodcode,prodname and avqty" and a table "que_for_choie" in mysql that has fields "procode,proname and avqty"
i want the trigger to update the value of "procode" in the linked server if the value of "prodcode" in sql server changes. this is what i have so far but it has errors,
create trigger [QFORCHOICE]
ON dbo.QFORCHOICE
FOR INSERT
AS
DECLARE #prodcode numeric(18,0)
DECLARE #prodname varchar(50)
DECLARE #avqty numeric(18,0)
BEGIN
SELECT
#procode = procode,
#proname = proname,
#avqty = avqty
FROM inserted
update [LINKED_MYSQL].[que_for_choice]
SET prodname=#prodname,avqty=#avqty
WHERE prodcode = #prodcode
end
can anybody please help.
thanks in advance
1- From within a trigger, you shouldn't attempt to access anything external to the current database. It will severely slow down any insert activity, and if there are any networking issues or the remote server is down for any reason, you'll then cause the original transaction to roll back. This is rarely the right thing to do
2- you're making the reliability of your system dependent on the reliability of two servers rather than one (say they both have 99% reliability - your system that ties them together with a trigger now has 98% overall reliability).

Ways to validate T-SQL queries?

I have access to an Access database and within that database are fields filled with TSQL queries. These queries are processed by T-SQL on a server. So when I write these SQL queries and put them into a field for use by the end server, I'm unable to validate the syntax/etc. I could create a temporary query in that Access database, but it's not the same query language. For example, Access would correctly use IIF but TSQL would not (it would instead be CASE).
I don't have direct access to this server with TSQL, is there a way I can validate my T-SQL queries (for syntax and the like)? Perhaps a web tool online?
I should note I do not have access to the SQL server. Only the Access db and that alone. I understand it will not validate table names and the like, I wouldn't expect it to.
Actually, a combination of MattMc3's answer and FremenFreedom's answer should work.
Download SQL Express.
Then, declare the following stored procedure:
create procedure IsValidSQL (#sql varchar(max)) as
begin
begin try
set #sql = 'set parseonly on;'+#sql;
exec(#sql);
end try
begin catch
return(1);
end catch;
return(0);
end; -- IsValidSQL
You can test it with:
declare #retval int;
exec #retval = IsValidSQL 'select iif(val, 0, 1) from t';
select #retval
or with:
declare #retval int;
exec #retval = IsValidSQL 'select val from t';
select #retval
Note: this will catch the IIF() issue. It will not catch anything related to the table structures or column structures. You would need the schema for that and a slightly different approach ("select top 0 * from () t") woudl do it.
You might be able to do something with SQL Fiddle online. However, I would suggest having a local copy of the database.
You can parse your T-SQL to check for valid syntax by executing it on the SQL Server machine with a SET PARSEONLY ON as the first line of your script. It will not validate table or field names, but will provide you with any syntax errors.
The Data Dude (Gert Drapers) describes how to use the built-in SQL Server T-SQL parser in your application here:
Getting to the Crown Jewels
If you want to only check the validity of the SQL statements that you have - this might be a nice way to go, and it doesn't require SQL Server per se to be installed where you run your unit tests.
It's a .NET based approach, and it cannot - of course - validate object names in your database if you're not using a live database - but it can catch syntactical errors in your T-SQL statements.
You can use the NOEXEC option:
SET NOEXEC ON
SELECT 1 AS Test
SET NOEXEC OFF
Is SQL Server Management Studio Express (free download) able to connect to regular SQL Server instances? If so, perhaps you could test the queries there. Even if you could not connect to the actual server, you might be able to create a test version of your database in Express that would at least allow you to catch syntax and naming problems.
If they are fairly static, convert them into stored procedures in the Sql Database and then just call them from access.

ODBC universal way to get deleted rows in trigger

Is there any universal way to get the deleted/inserted/updated rows in trigger? I want to create one trigger (I mean one pice of code in my application), which should work on Oracle, Sql Server and Postgres. Is it possible? I'm using odbc drivers to connect to different dbs.
It's working in SQL Server, but not in Oracle.
CREATE TRIGGER schema.trg_nameON schema.table_name
FOR DELETE
AS
BEGIN
DECLARE #id BIGINT;
SELECT #id = d.ID
FROM deleted d
DELETE
FROM schema.table_name
WHERE TOP_ID = #id;
END
no, each RDMS will have its own syntax. The syntax you used is a sql server syntax.
what do you mean by create trigger on the application? Please provide us with more info

sp_generate_inserts for all the tables? or something similar

I have two databases.
Database A - full of data
Database B - backup of database A, but without data
how can I get all data from database A and just merge it into database B?
My thoughts were to just generate an insert of the whole data or something.
Thanks
Take a look at redgate's SQL Data Compare.
OP said:
database is full of triggers and
constraints
Just restore a complete backup of A as a new database and be done with it. Lots of "one off" inserts created by a script will take forever, play havoc with your transaction log, and most likely fail because of FKs, etc.
That would work if you're trying to do something ongoing, but if you want to do it just once and you have SQL Server Management Studio installed, you can have it do the Export/Import for you. Here's a walk-though with some screenshots:
http://www.databasejournal.com/features/mssql/article.php/3580216/SQL-Server-2005-Import--Export-Wizard.htm
If you don't have any identity fields to worry about, and it's a one-time operation, you can do something like this, which uses sp_msforeachtable and dynamic SQL:
DECLARE #SQL varchar(max)
SET #SQL = '
INSERT INTO DatabaseB.? WITH (TABLOCK)
SELECT *
FROM DatabaseA.?'
exec sp_MSforeachtable #SQL