How to find all trigger associated with a table with SQL Server? - sql-server

I created a trigger for a table in SQL Server and it works for me.
My problem is: How do find it and modify it?
I use this query to find my triggers:
select * from sys.triggers
This find all triggers, but how to open it and change the triggers?

You can do this simply with SSMS. Just go to your table name and expand the Triggers node to view a list of triggers associated with that table. Right click to modify your trigger.

select so.name, text
from sysobjects so, syscomments sc
where type = 'TR'
and so.id = sc.id
and text like '%YourTableName%'
This way you can list out all the triggers associated with the given table.

This might be useful
SELECT
t.name AS TableName,
tr.name AS TriggerName
FROM sys.triggers tr
INNER JOIN sys.tables t ON t.object_id = tr.parent_id
WHERE
t.name in ('TABLE_NAME(S)_GOES_HERE');
This way you just have to plugin the name of tables and the query will fetch all the triggers you need

select m.definition from sys.all_sql_modules m inner join sys.triggers t
on m.object_id = t.object_id
Here just copy the definition and alter the trigger.
Else you can just goto SSMS and Expand the your DB and under Programmability expand Database Triggeres then right click on the specific trigger and click modify there also you can change.

use sp_helptrigger to find the triggerlist for the associated tables

find triggers on table:
select so.name, text
from sysobjects so, syscomments sc
where type = 'TR'
and so.id = sc.id
and text like '%TableName%'
and you can find store procedure which has reference of table:
SELECT Name
FROM sys.procedures
WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%yourtablename%'

Go through
Need to list all triggers in SQL Server database with table name and table's schema
This URL have set of queries by which you can get the list of triggers associated with particular table.
I believe you are working in sqlserver following are the steps to get modify triggers
To modify a trigger
Expand a server group, and then expand a server.
Expand Databases, expand the database in which the table containing
the trigger belongs, and then click Tables.
In the details pane, right-click the table on which the trigger
exists, point to All Tasks, and then click Manage Triggers.
In Name, select the name of the trigger.
Change the text of the trigger in the Text field as necessary. Press
CTRL+TAB to indent the text of a SQL Server Enterprise Manager
trigger.
To check the syntax of the trigger, click Check Syntax.

With this query you can find all Trigger in all tables and all views.
;WITH
TableTrigger
AS
(
Select
Object_Kind = 'Table',
Sys.Tables.Name As TableOrView_Name ,
Sys.Tables.Object_Id As Table_Object_Id ,
Sys.Triggers.Name As Trigger_Name,
Sys.Triggers.Object_Id As Trigger_Object_Id
From Sys.Tables
INNER Join Sys.Triggers On ( Sys.Triggers.Parent_id = Sys.Tables.Object_Id )
Where ( Sys.Tables.Is_MS_Shipped = 0 )
),
ViewTrigger
AS
(
Select
Object_Kind = 'View',
Sys.Views.Name As TableOrView_Name ,
Sys.Views.Object_Id As TableOrView_Object_Id ,
Sys.Triggers.Name As Trigger_Name,
Sys.Triggers.Object_Id As Trigger_Object_Id
From Sys.Views
INNER Join Sys.Triggers On ( Sys.Triggers.Parent_id = Sys.Views.Object_Id )
Where ( Sys.Views.Is_MS_Shipped = 0 )
),
AllObject
AS
(
SELECT * FROM TableTrigger
Union ALL
SELECT * FROM ViewTrigger
)
Select
*
From AllObject
Order By Object_Kind, Table_Object_Id

select B.name
from sys.objects A
join sys.triggers B
on A.object_id = B.parent_id
where A.name ='Table_name' /*Table Name*/

select o1.name as trigger_name,o2.name as table_name from sys.objects o1
join sys.objects o2 on
o1.parent_object_id=o2.object_id
where o1.type='TR'
and o2.name='my_table'

You Can View All trigger related to your database by below query
select * from sys.triggers
And for open trigger you can use below syntax
sp_helptext 'dbo.trg_InsertIntoUserTable'

Much simple query below
select (select [name] from sys.tables where [object_id] = tr.parent_id ) as TableName ,* from sys.triggers tr

select * from information_schema.TRIGGERS;

select t.name as TriggerName,m.definition,is_disabled
from sys.all_sql_modules m
inner join
sys.triggers t
on m.object_id = t.object_id
inner join sys.objects o
on o.object_id = t.parent_id
Where o.name = 'YourTableName'
This will give you all triggers on a Specified Table

Try to Use:
select * from sys.objects where type='tr' and name like '%_Insert%'

you can open your trigger with
sp_helptext yourtriggername

Related

How can I search for stored procedures executing other stored procedures?

I have a list of about 350 stored procedures like this:
usp_SP1,
usp_SP2
...
I want to search through each one looking to see if any of them call other stored procedures or other databases?
I guess I would look for a line like 'exec something' in each one or a specific name of a database. ex. some_other_database
How would I do this to give me a list of the stored procedures that call other stored procedures or contain some specific string? ex. "some other database name"
I can run this below but it finds just the text. is there any way I can ensure it's a exec call and not just text?
USE [Your_DB];
GO
SELECT
ROUTINE_NAME, ROUTINE_DEFINITION
FROM
INFORMATION_SCHEMA.ROUTINES
WHERE
ROUTINE_DEFINITION LIKE '%exec %'
AND ROUTINE_TYPE = 'PROCEDURE'
AND ROUTINE_NAME IN ('usp_SP1', 'usp_SP2')
GO
You can query the sys.sql_dependencies view, like this:
SELECT o1.name AS CallerSP, o2.name AS CalledSP
FROM sys.sql_dependencies sd
INNER JOIN sys.objects o1 ON o1.object_id = sd.object_id
INNER JOIN sys.objects o2 ON o2.object_id = sd.referenced_major_id
WHERE o1.type='P' AND o2.type='P'
You may need to call sp_refreshsqlmodule for all objects before executing this query, if the called SP was created after the caller.
Other options could be to query the sys.sql_expression_dependencies view or the sys.dm_sql_referenced_entities function.
Not to compete, Razvan Socol is correct. Adding the ways to do it in earlier version back to 2000. All the old tables and views are still query-able even if not visible in ssms.
select distinct /* I believe the sys.sys views were added in 2012 or so, still works in 2017 */
od.name caller_procedure_name
,o.name called_procedure_name
from sys.sysdepends d
inner join sys.sysobjects o on o.id = d.depid and o.type = 'P'
inner join sys.sysobjects od on od.id = d.id and od.type = 'P'
select distinct /* should work all the way back to sql 2000, still works in 2017 */
od.name caller_procedure_name
,o.name called_procedure_name
from dbo.sysdepends d
inner join dbo.sysobjects o on o.id = d.depid and o.type = 'P'
inner join dbo.sysobjects od on od.id = d.id and od.type = 'P'

auto pick schema change of underlying table for view

I know that the sql server doesnt pick the schema change of underlying table. for example, if we execute the following,
CREATE TABLE tbl (id INT)
CREATE VIEW viewa
AS
SELECT *
FROM tbl
ALTER TABLE tbl ADD NAME INT
and execute a select on view, only ID column is returned
SELECT *
FROM viewa
Is there any property I can set by which the sql engine autopicks the schema changes
use sp_refreshview for this,
exec sp_refreshview N'dbo.viewa'
There's no out of the box functionality for this. But you could roll your own. The system tables detail all the columns currently attached to each view and table.
-- Returns every column for the given table/view.
SELECT
c.*
FROM
sys.objects AS o
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
INNER JOIN sys.columns AS c ON c.object_id = o.object_id
WHERE
s.name = 'MySchema'
AND o.name = 'MyTable'
;
You would need to create a control table that maps your tables to views. You would also need to schedule the process.
You can create view with "SCHEMABINDING" option. That way base table definition cannot be modified in a way that could affect view definition.
CREATE VIEW viewa
AS
SELECT *
FROM tbl SCHEMABINDING

How to get the list of active triggers on a database?

My application is based on a sql server db.
All customers has the same db except for customizations.
Some customizations include: new tables, modified tables, custom views, custom triggers...
When I run the software update some scripts are executed. Now I manually disable triggers and reenable after the scripts are done.
Anyway I would like automatically to disable all the triggers (that are enabled, may be some of them could be already disabled) and then reenable them at the end.
Not to reinvent the whell, how to do that?
How to get only the active triggers on the current db?
Once I got this I can programmatically create and run the
DISABLE TRIGGER triggername ON TABLENAME
ENABLE TRIGGER triggername ON TABLENAME
select objectproperty(object_id('TriggerName'), 'ExecIsTriggerDisabled')
1 means true, 0 means false obviously
Use Jeff O's query and modify it a bit
SELECT
TAB.name as Table_Name
, TRIG.name as Trigger_Name
, TRIG.is_disabled --or objectproperty(object_id('TriggerName'), 'ExecIsTriggerDisabled')
FROM [sys].[triggers] as TRIG
inner join sys.tables as TAB
on TRIG.parent_id = TAB.object_id
or add it as a where clause.
where TRIG.is_disabled = 0 -- or 1 depends on what you want
SELECT *
FROM sys.triggers
WHERE is_disabled = 0
SELECT
TAB.name as Table_Name
, TRIG.name as Trigger_Name
FROM [sys].[triggers] as TRIG
inner join sys.tables as TAB
on TRIG.parent_id = TAB.object_id
SELECT
TAB.name as Table_Name,
TRIG.name as Trigger_Name,
Comments.Text TriggerText
FROM [sys].[triggers] as TRIG
Inner Join sys.tables as TAB on TRIG.parent_id = TAB.object_id
Inner Join syscomments Comments On TRIG.object_id = Comments.id
WHERE
TRIG.is_disabled = 0;
is complete solution
select * from sys.triggers
Here object_id is for table so from joining sys.table you can get table name
You can query the sys.triggers view.
select so.name, text
from sysobjects so, syscomments sc
where type = 'TR'
and so.id = sc.id
and text like '%related_table_name%'
Here is the query that occurs when you do a refresh on "Database Triggers" in SSMS.
SELECT
tr.name AS [Name],
'Server[#Name=' + quotename(CAST(
serverproperty(N'Servername')
AS sysname),'''') + ']' + '/Database[#Name=' + quotename(db_name(),'''') + ']' + '/DdlTrigger[#Name=' + quotename(tr.name,'''') + ']' AS [Urn],
tr.is_disabled AS [IsEnabled]
FROM
sys.triggers AS tr
WHERE
(tr.parent_class = 0)
ORDER BY
[Name] ASC
Using that, I've created a version (that enhances the accepted answer) to include the database triggers.
Note the left join and the COALESCE check.
SELECT
COALESCE(TAB.name, 'DATABASE') as TargetObjectName
, TRIG.name as Trigger_Name
, TRIG.is_disabled --or objectproperty(object_id('TriggerName'), 'ExecIsTriggerDisabled')
-- select *
FROM [sys].[triggers] as TRIG
left join sys.tables as TAB
on TRIG.parent_id = TAB.object_id
WHERE
/* (TRIG.parent_class = 0) and */
TRIG.is_disabled = 0
//Use Your Database
use [your_database_Name]
Select * from sys.triggers where is_disabled=0

Can I select all the tables with more than one update trigger

Can I select all the tables with more than one update trigger? The following code selects all the tables with more than one trigger, but I need only the tables with more than one update trigger.
This query also returns tables with one insert trigger and one update one, which is not what I want.
SELECT * FROM sys.triggers
WHERE parent_id IN(SELECT parent_id
FROM sys.triggers
GROUP BY parent_id
HAVING COUNT(*)>1)
You should be able to tell this from sys.trigger_events, e.g:
SELECT *
FROM sys.trigger_events AS te
INNER JOIN sys.triggers AS t
ON t.[object_id] = te.[object_id]
WHERE te.[type] IN (1,2,3);
So to get tables with more than one update trigger:
SELECT OBJECT_NAME(parent_id)
FROM sys.triggers AS t
INNER JOIN sys.trigger_events AS te
ON t.[object_id] = te.[object_id]
WHERE te.type_desc = 'UPDATE'
GROUP BY OBJECT_NAME(parent_id)
HAVING COUNT(*) > 1;
Not very reliable, but it should work if you need something quick and dirty.
SELECT * FROM sys.triggers
WHERE parent_id IN
(SELECT parent_id
FROM sys.triggers tt
JOIN sys.syscomments sc on sc.id=tt.object_id
WHERE sc.text LIKE '%AFTER UPDATE%'
GROUP BY parent_id
HAVING COUNT(*)>1)

How do I get a list of tables affected by a set of stored procedures?

I have a huge database with some 100 tables and some 250 stored procedures. I want to know the list of tables affected by a subset of stored procedures. For example, I have a list of 50 stored procedures, out of 250, and I want to know the list of tables that will be affected by these 50 stored procedures. Is there any easy way for doing this, other than reading all the stored procedures and finding the list of tables manually?
PS: I am using SQL Server 2000 and SQL Server 2005 clients for this.
This would be your SQL Server query:
SELECT
[NAME]
FROM
sysobjects
WHERE
xType = 'U' AND --specifies a user table object
id in
(
SELECT
sd.depid
FROM
sysobjects so,
sysdepends sd
WHERE
so.name = 'NameOfStoredProcedure' AND
sd.id = so.id
)
Hope this helps someone.
sp_depends 'StoredProcName' will return the object name and object type that the stored proc depends on.
EDIT: I like #KG's answer better. More flexible IMHO.
I'd do it this way in SQL 2005 (uncomment the "AND" line if you only want it for a particular proc):
SELECT
[Proc] = SCHEMA_NAME(p.schema_id) + '.' + p.name,
[Table] = SCHEMA_NAME(t.schema_id) + '.' + t.name,
[Column] = c.name,
d.is_selected,
d.is_updated
FROM sys.procedures p
INNER JOIN sys.sql_dependencies d
ON d.object_id = p.object_id
AND d.class IN (0,1)
INNER JOIN sys.tables t
ON t.object_id = d.referenced_major_id
INNER JOIN sys.columns c
ON c.object_id = t.object_id
AND c.column_id = d.referenced_minor_id
WHERE p.type IN ('P')
-- AND p.object_id = OBJECT_ID('MyProc')
ORDER BY
1, 2, 3
One very invasive option would be to get a duplicate database and set a trigger on every table that logs that something happened. Then run all the SP's. If you can't do lots of mods to the DB that wont work
Also, be sure to add the logging to existing triggers rather than replace them with logging if you also want tables that the SP's effect via triggers.

Resources