extract a string from a stored proc definition - sql

I need to check the library used by several stored procs that extract data from a remote server.
I have (with SO help, see SO 21708681) built the below code:
DECLARE #tProcs TABLE
(
procID int IDENTITY,
procObjectID nvarchar(100),
procName nvarchar(100)
);
insert into #tProcs
SELECT object_id, name
FROM sys.objects
WHERE type in (N'P', N'PC') and name like '%_Extract'
declare #countProcs int, #I int=0
select #countProcs=COUNT(*) from #tProcs
while #I<#countProcs
Begin
declare #source_code nvarchar(max)
declare #objectID nvarchar(50)
declare #proc_Name nvarchar(200)
select #objectID=procObjectID from #tProcs where procID=#I
select #proc_Name=procName from #tProcs where procID=#I
select #source_code = definition
from sys.sql_modules
where object_id = #objectID
SELECT PATINDEX('BOCTEST.%', #proc_Name) as Pos, #proc_Name
-- or SELECT charindex(#source_code, '%BOCTEST%')
set #I=#I+1
End
Inside each of the target stored procs there is a line like this:
DECLARE YP040P_cursor CURSOR FOR SELECT * FROM BOCTEST.S653C36C.LIVEBOC_A.YP040P
I need to know for each of the stored procs the part 'LIVEBOC_A' (which can either be 'LIVEBOC_A' or LIVEBOC_B)
I tried to use PATINDEX and CHARINDEX to get the location of the start opf that string in the definition from sysmodules but all I get back is either zero or an error that string or binary data would be truncated.

try
SELECT
name,
table_name = CASE WHEN OBJECT_DEFINITION(OBJECT_ID) LIKE '%BOCTEST.S653C36C.LIVEBOC_A.YP040P%' THEN 'LIVEBOC_A'
WHEN OBJECT_DEFINITION(OBJECT_ID) LIKE '%BOCTEST.S653C36C.LIVEBOC_B.YP040P%' THEN 'LIVEBOC_B' END
FROM sys.objects o
WHERE o.[type] IN ('P', 'PC')
AND name like '%_Extract'

You can do what you want with a query like this one:
select name = s.name + '.' + p.name ,
dt_created = p.create_date ,
dt_modified = p.modify_date ,
livboc_usage = case
when m.definition like '%declare%cursor%boctext.[^.].LIVEBOC_A.%' then 'A'
when m.definition like '%declare%cursor%boctext.[^.].LIVEBOC_B.%' then 'B'
else null
end
from sys.schemas s
join sys.procedures p on p.schema_id = s.schema_id
join sys.sql_modules m on m.object_id = p.object_id
But since what you're looking for are cross-server dependencies of a table, you should be able to get that simply by querying the system view sys.sql_expression_dependencies, which
Contains one row for each by-name dependency on a user-defined entity in the current
database. A dependency between two entities is created when one entity, called the
referenced entity, appears by name in a persisted SQL expression of another entity,
called the referencing entity. For example, when a table is referenced in the definition
of a view, the view, as the referencing entity, depends on the table, the referenced
entity. If the table is dropped, the view is unusable.
You can use this catalog view to report dependency information for the following
entities:
Schema-bound entities.
Non-schema-bound entities.
Cross-database and cross-server entities.
Entity names are reported; however, entity IDs are not resolved.
Column-level dependencies on schema-bound entities.
Column-level dependencies for non-schema-bound objects can be returned
by using sys.dm_sql_referenced_entities.
Server-level DDL triggers when in the context of the master database.
To that end, running a query like this in the database the referencing stored procedures live should do you:
select name = o.name ,
type = o.type_desc ,
liveboc_usage = case d.referenced_schema_name
when 'liveboc_a' then 'A'
when 'liveboc_b' then 'B'
else null
end ,
has_dependency_on = d.referenced_server_name
+ '.' + d.referenced_database_name
+ '.' + d.referenced_schema_name
+ '.' + d.referenced_entity_name
from sys.sql_expression_dependencies d
join sys.objects o on o.object_id = d.referenced_id
join sys.schemas s on s.schema_id = o.schema_id
where d.referenced_server_name = 'BOCTEST'
and d.referenced_database_name = 'S653C36C'
and d.referenced_schema_name like 'LIVEBOC_[AB]'
and d.referenced_entity_name = 'YP040P'

Related

How to check all stored procedures which update a specific column

Following is the sample to search stored procedures which have the keyword Student in them:
SELECT TOP (1000) *
FROM [eUniversityManagement].[sys].[all_sql_modules]
WHERE definition LIKE '%Student%'
I just wondering can we search any stored procedure that has and UPDATE on Student.name for example:
UPDATE STUDENT
SET Name = #Name,
Address = #Address,
DOB = #DOB
WHERE id = #StudentID
Thanks.
You can use the sys.dm_sql_referenced_entities function for this. It's a little complicated, as it wants the procedure name which references the column, so you need to start off with all objects and apply the functions
SELECT o.name, schema_name = s.name
FROM sys.objects o
JOIN sys.schemas s ON s.schema_id = o.schema_id
CROSS APPLY sys.dm_sql_referenced_entities (QUOTENAME(s.name) + '.' + QUOTENAME(o.name), 'OBJECT') r
WHERE o.type IN ('P', 'TR')
AND r.referenced_entity_name = 'student'
AND r.referenced_minor_name = 'Name'
AND r.is_updated = 1;

Get Nested Stored Procedure Dependencies

I have inherited a number of very large stored procedures with nested stored procedures inside. I wanted to create a stored procedure I could run to show me all the dependencies for a particular stored procedure - listing all the tables and nested stored procedures within it.
I am using the following code but this only gives me the top level dependencies and not anything from the nested stored procedures
CREATE TABLE #TEMP_ROADMAP
(
TBL_OBJECT_NAME VARCHAR(50),
TBL_TYPE VARCHAR(20),
TBL_PARENT VARCHAR(20),
PROCNAME VARCHAR(50)
)
DECLARE #PARENTPROC VARCHAR(100)
SET #PARENTPROC = '[DBO].[RULE_PROC_1]'
INSERT INTO #TEMP_ROADMAP (TBL_OBJECT_NAME,TBL_TYPE)
SELECT DISTINCT
[OBJECT_NAME] = SCHEMA_NAME(O.[SCHEMA_ID]) + '.' + O.NAME, O.TYPE_DESC
FROM
SYS.DM_SQL_REFERENCED_ENTITIES (#PARENTPROC, 'OBJECT') D
JOIN
SYS.OBJECTS O ON D.REFERENCED_ID = O.[OBJECT_ID]
WHERE
O.[TYPE] IN ('U', 'V', 'P', 'IF', 'FN')
UPDATE #TEMP_ROADMAP
SET TBL_PARENT = 'PARENT',
PROCNAME = #PARENTPROC
WHERE TBL_OBJECT_NAME IS NOT NULL
SELECT * FROM #TEMP_ROADMAP
DROP TABLE #TEMP_ROADMAP
Output:
TBL_OBJECT_NAME TBL_TYPE TBL_PARENT PROCNAME
dbo.RULE_PROC_2 SQL_STORED_PROCEDURE PARENT [DBO].[RULE_PROC_1]
dbo.TEST_TABLE_1 USER_TABLE PARENT [DBO].[RULE_PROC_1]
Can it done where I can get the tables and name of the other nested stored procedures in this parent procedure?
Sorry if I misunderstand you but I think you need this :-
EXECUTE SP_DEPENDS <PROCNAME>

Is there a way to find all invalid columns that are referenced in a view using SQL Server 2012?

I have inherited a large database project with thousands of views.
Many of the views are invalid. They reference columns that no longer exist. Some of the views are very complex and reference many columns.
Is there an easy way to track down all the incorrect columns references?
This answer finds the underlying columns that were originally defined in the views by looking at sys.views, sys.columns and sys.depends (to get the underlying column if the column has been aliased). It then compares this with the data held in INFORMATION_Schema.VIEW_COLUMN_USAGE which appears to have the current column usage.
SELECT SCHEMA_NAME(v.schema_id) AS SchemaName,
OBJECT_NAME(v.object_id) AS ViewName,
COALESCE(alias.name, C.name) As MissingUnderlyingColumnName
FROM sys.views v
INNER JOIN sys.columns C
ON C.object_id = v.object_id
LEFT JOIN sys.sql_dependencies d
ON d.object_id = v.object_id
LEFT JOIN sys.columns alias
ON d.referenced_major_id = alias.object_id AND c.column_id= alias.column_id
WHERE NOT EXISTS
(
SELECT * FROM Information_Schema.VIEW_COLUMN_USAGE VC
WHERE VIEW_NAME = OBJECT_NAME(v.object_id)
AND VC.COLUMN_NAME = COALESCE(alias.name, C.name)
AND VC.TABLE_SCHEMA = SCHEMA_NAME(v.schema_id)
)
For the following view:
create table test
( column1 varchar(20), column2 varchar(30))
create view vwtest as select column1, column2 as column3 from test
alter table test drop column column1
The query returns:
SchemaName ViewName MissingUnderlyingColumnName
dbo vwtest column1
This was developed with the help of this Answer
UPDATED TO RETRIEVE ERROR DETAILS
So this answer gets you what you want but it isn't the greatest code.
A cursor is used (yes I know :)) to execute a SELECT from each view in a TRY block to find ones that fail. Note I wrap each statement with a SELECT * INTO #temp FROM view X WHERE 1 = 0 this is to stop the EXEC returning any results and the 1=0 is so that SQL Server can optimize the query so that it is in effect a NO-OP.
I then return a list of any views whose sql has failed.
I haven't performed lots of testing on this, but it appears to work. I would like to get rid of the execution of each SELECT from View.
So here it is:
DECLARE curView CURSOR FOR
SELECT v.name AS ViewName
FROM sys.views v
INNER JOIN sys.sql_modules m
on v.object_id = m.object_id
OPEN curView
DECLARE #viewName SYSNAME
DECLARE #failedViews TABLE
(
FailedViewName SYSNAME,
ErrorMessage VARCHAR(MAX)
)
FETCH NEXT FROM curView
INTO #ViewName
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRY
exec ('SELECT * INTO #temp FROM ' + #viewName + ' WHERE 1=0' )
END TRY
BEGIN CATCH
INSERT INTO #failedViews VALUES (#viewName, ERROR_MESSAGE())
END CATCH
FETCH NEXT FROM curView
INTO #ViewName
END
CLOSE curView
DEALLOCATE curView
SELECT *
FROM #failedViews
An example of an ERROR returned is:
FailedViewName ErrorMessage
--------------- -------------
vwtest Invalid column name 'column1'.
You could use system tables get information.
SELECT v.VIEW_NAME,v.TABLE_CATALOG,v.TABLE_SCHEMA,v.TABLE_NAME,v.COLUMN_NAME
from INFORMATION_SCHEMA.VIEW_COLUMN_USAGE v
left outer join INFORMATION_SCHEMA.COLUMNS c
ON v.TABLE_CATALOG=c.TABLE_CATALOG AND v.TABLE_SCHEMA=c.TABLE_SCHEMA AND v.TABLE_NAME=c.TABLE_NAME AND v.COLUMN_NAME=c.COLUMN_NAME
WHERE c.TABLE_NAME IS NULL
ORDER BY v.VIEW_NAME

How to identify whether the table has identity column

I want to find out whether the table has an identity column or not. Table is unknown to me. I have not done the structure of the table. Using Query?
I am using Sql Server Compact Edition.
IF (OBJECTPROPERTY(OBJECT_ID('TABLE_NAME'), 'TableHasIdentity') = 1)
ObjectProperty is available starting sql server 2008 Reference:
OBJECTPROPERTY
This query returns a table's identity column name:
CREATE PROCEDURE dbo.usp_GetIdentity
#schemaname nvarchar(128) = 'dbo'
,#tablename nvarchar(128)
AS
BEGIN
SELECT OBJECT_NAME(OBJECT_ID) AS TABLENAME,
NAME AS COLUMNNAME,
SEED_VALUE,
INCREMENT_VALUE,
LAST_VALUE,
IS_NOT_FOR_REPLICATION
FROM SYS.IDENTITY_COLUMNS
WHERE OBJECT_NAME(OBJECT_ID) = #tablename
AND OBJECT_SCHEMA_NAME(object_id) = #schemaname
END
Then form the code side.
Call this stored procedure using the datareader role, then check datareader.hasrows(). If the condition value is true (1), then the table has identity column if set. If not then it doesn't have an identity column.
I know it's long time ago but i found this helpful
try this :
IF EXISTS (SELECT * from syscolumns where id = Object_ID(#TABLE_NAME) and colstat & 1 = 1)
BEGIN
-- Do your things
END
Any of the below queries can be used to check if an Identity Column is present in the table
1)
SELECT *
FROM sys.identity_columns
WHERE OBJECT_NAME(object_id) = 'TableName'
2)
SELECT *
FROM sys.identity_columns
WHERE object_id = (
SELECT id
FROM sysobjects
WHERE name = 'TableName'
)
I would just like to add this option as well as I think it is the simplest
SELECT COLUMNPROPERTY(OBJECT_ID('TableName'),'ColumnName','isidentity')
One way to do this would be to make use of the stored procedure sp_help. I.e:
sp_help MyTable
This will return a DataSet that has all the information you would need on the table. There is a specific Table that has information on identities.
I.e:
If it does not contain an identity field, the Identity column will say: "No identity column defined".
#Pranay: he said Compact Edition. Stored procedures aren't supported, and there is no sys.anything.
This is the call:
SELECT Count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE AUTOINC_INCREMENT IS NOT NULL AND TABLE_NAME='this_table'
It will return either 1 (true) or 0 (false).
...
declare #tblhasIdentCol bit = IF (IDENT_CURRENT( #dbName +'.'+ #schemaName +'.'+ #tableName ) IS NOT NULL , 1 , 0 )
You get numeric value if table has identity
Very simple answer would be to run this:
SELECT IDENT_CURRENT('TABLE-NAME')
This would give max value of identity column if exists, if the column doesn't exist, it gives 1 as result.
Based on max value, you can identify which column is having that and determine the identity column.
This the query that get u all the tableNames, columnnames of the table, and is_identity or not in the selected database
SELECT
sys.columns.name
, sys.tables.name
, is_identity
FROM sys.columns
INNER JOIN sys.tables ON sys.tables.object_id = sys.columns.object_id
AND sys.columns.is_identity = 1
CREATE FUNCTION dbo.fnTableHasIdentity(#Tbl sysname)
RETURNS TINYINT
BEGIN
RETURN OBJECTPROPERTY(OBJECT_ID(#Tbl), 'TableHasIdentity')
END
--As simple as that!
select t.name as TableName,c.name as ColumnName
from sys.identity_columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = 'TableName'
If you like me, needed to be able to do this for tables in an arbitrary database, then I found the following solution:
IF EXISTS (
SELECT 1
FROM [database name].sys.identity_columns AS id_col
INNER JOIN [database name].sys.objects
ON objects.object_id = id_col.object_id
INNER JOIN [database name].sys.schemas
ON schemas.schema_id = objects.schema_id
AND schemas.name = 'schema name'
WHERE OBJECT_NAME(id_col.object_id, DB_ID('database name')) = 'table name'
) SELECT 1 ELSE SELECT 0
you can get the 1 or 0 Boolean Form if the current table has identity Columns by using this
SELECT Count(Column_ID) FROM sys.identity_columns WHERE OBJECT_NAME(object_id) = 'tableName'
One way to list all Tables with their identity column if it exists
to get you desired table add at the end of the filter "and o.name='TableName'"
where Tbale Nam is the table you are looking for
SELECT o.[Name][TableName],i.[name][IdentityColName] FROM
sys.objects o
left outer join sys.identity_columns i on i.object_id=o.object_id
where o.type='U'

How to Find the list of Stored Procedures which affect a particular column?

Im working on this large DB which has a lot of the business knowledge embedded in the SPs[I know!] and there is a lot of chaining between the SPs. i.e one stored proc calling another.
Im want to find out a list of stored procedures which update a particular column. How would I do that.
Using showplan_All as outlined in
SQL Table and column Parser for stored procedures doesnt work for me, because this is a shared dev db.
using a Sp from master db scanning system text as described is not feasible because I dont have access to the master db.
So how can I find this informaion?
From system view sys.sql_dependencies you can get dependencies at column level.
DECLARE #Schema SYSNAME
DECLARE #Table SYSNAME
DECLARE #Column SYSNAME
SET #Schema = 'dbo'
SET #Table = 'TableName'
SET #Column = 'ColumnName'
SELECT o.name
FROM sys.sql_dependencies AS d
INNER JOIN sys.all_objects AS o ON o.object_id = d.object_id
INNER JOIN sys.all_objects AS ro ON ro.object_id = d.referenced_major_id
INNER JOIN sys.all_columns AS c ON c.object_id = ro.object_id AND c.column_id = d.referenced_minor_id
WHERE (SCHEMA_NAME(ro.schema_id)=#Schema)
and o.type_desc = 'SQL_STORED_PROCEDURE'
and ro.name = #Table
and c.name = #Column
GROUP BY o.name
Have you tried this : EXEC sp_depends #objname = [table name of the column you are interested in].
So for example, if you had a column named Price in a table named Product, you would execute this: EXEC sp_depends #objname = N'Product'.
Simply executing this would give you list of all sps, views, etc which depend on that particular table.
I use this all the time as I work with a db which has over 400 tables :-)
sp_depends page on MSDN
Try something like this:
use YourDatabase;
select [Name]
from sys.procedures
where object_definition([object_id]) like '%YourColumnName%';
Obviously this has the potential to generate a lot of false positives depending on what the column is named but at least you will have a list of procedures to sift through.
Here's one that works in SQL 2000+; Note that as Andrew noted in his, you will get false positives depending on your column name, but it's a starting place:
SELECT DISTINCT o.Name
FROM syscomments c
JOIN sysobjects o ON c.ID = o.ID
WHERE c.Text LIKE '%ColumnName%'
ORDER BY o.Name
use msdb
go
select * from sysjobs j
inner join sysjobsteps s
on j.job_id=s.job_id
where command like '%HBR_INSTRUMENT%'