Search string in SQL with action on table - sql

I found on internet some stored procedure to search string in database, regularly it's used by table name.
My procedure contains a SELECT statement like this:
select distinct s.name
from sysobjects s
inner join syscomments c on c.id = s.id
and charindex(#keyword,c.text) > 0
where s.type IN ('V', 'P')
order by 1
My action want more than this, I want to search table name with action on that like insert, update or select. It means only find table name(keyword) has action insert or update or select and show me where it's used (procedure name, view...)
Is it possible to do?

First, dont use sysobjects and syscomments as they have been deprecated for quite some time now.
If you just care that the word appears in the object text, you can use a wildcard search like this
select top 100 *
from sys.sql_modules sm
inner join (select searchString = 'insert' union all
select searchString = 'update' union all
select searchString = 'delete') x
on sm.definition like '%' + x.searchString + '%'

Related

List the tables used by the sql script, and the nature of access to the table

I have a script with thousand of lines and I want to extract all the tables (& temp tables) the script references, and also the nature of access to the table such as select, insert, update or delete. Is there a tool we can use for this purpose?
Sample script (input):
SELECT * FROM Table1
UPDATE Table1 SET Col1 = 1
DELETE FROM Table2
EXEC 'INSERT INTO #Table3 SELECT ''Test'''
Sample output:
1. Table1 - select, update
2. Table2 - delete
3. #Table3 - insert
You may find the following query useful, however, one thing it doesn't give you is the references from dynamic SQL statements (and perhaps also table variables and temp tables).
I think to get the level of information you're looking for you'd probably need to write your own script/program. Previously I wrote something that gave me the results from the below query, including any dynamic SQL references, in C# using SQL Server Management Objects (SMO).
SELECT DISTINCT
OBJECT_SCHEMA_NAME(D.referencing_id) referencing_object_schema
, OBJECT_NAME(D.referencing_id) referencing_object_name
, O.[type_desc] referencing_object_type
, D.referenced_schema_name
, D.referenced_entity_name
, D.referenced_id
,
CASE
WHEN O_REF.[object_id] IS NOT NULL THEN O_REF.[type_desc]
WHEN T.user_type_id IS NOT NULL THEN 'USER_DEFINED_TYPE'
END referenced_object_type
FROM
sys.sql_expression_dependencies D
LEFT JOIN sys.objects O ON D.referencing_id = O.[object_id]
LEFT JOIN sys.objects O_REF ON D.referenced_id = O_REF.[object_id]
LEFT JOIN sys.types T ON D.referenced_id = T.user_type_id
There is a system function called: fn_dblog. You could use it as below:
IF OBJECT_ID('tempdb..#tempLog') IS NOT NULL DROP TABLE #tempLog
-- Raw Data
SELECT DISTINCT
[AllocUnitName],
Operation
INTO #tempLog
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation IN ('LOP_INSERT_ROWS','LOP_MODIFY_ROW',
'LOP_DELETE_ROWS','LOP_BEGIN_XACT','LOP_COMMIT_XACT')
AND [AllocUnitName] is not null
ORDER By [AllocUnitName], Operation
-- SELECT * FROM #tempLog
-- Display Enhancement and Grouping
SELECT [AllocUnitName], Operations = STUFF((
SELECT N', ' + REPLACE(operation,'LOP_', '')
FROM #tempLog
WHERE [AllocUnitName] = x.[AllocUnitName]
FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM #tempLog AS x
WHERE [AllocUnitName] is not null
GROUP BY [AllocUnitName]
ORDER BY [AllocUnitName]

T-SQL Query to get table dependencies for all tables in database

I have the start of a query below which gives me dependencies of a particular table:
SELECT DISTINCT OBJECT_NAME(object_id) AS referencing_object_name
FROM sys.sql_dependencies
WHERE referenced_major_id = OBJECT_ID('TABLE_NAME_HERE')
But is there a way to alter this to show:
1) The above with a column with tablename being populated
2) The above relating to ALL tables within a set database (not just a single table as the original query shows)
3) All results on a single row
Final output looking like image below:
screenshotoffinalquery
.
.
.
EDIT:
I seem to be very close with this, but last column is duplicating a single result
SELECT DISTINCT b.name, a.referenced_major_id, b.object_id,
substring((
SELECT ' || ' +OBJECT_NAME(a.object_id)
FROM sys.sql_dependencies a JOIN sys.tables b ON a.referenced_major_id = b.object_id
For XML PATH ('')
), 2, 1000) AS [TextLine]
FROM sys.sql_dependencies a JOIN sys.tables b ON a.referenced_major_id = b.object_id
ORDER BY b.name ASC

SQL Server 2008 - Union of 4 queries and ordering by relevance

I'm facing an issue that my query cannot order by relevance since I declared 'column' MATCH and try to ordering by it.
I'm trying to create a stored procedure using UNION.
This query has some rules that I need to follow since I need to bring 3 related articles. Each rule has a query that I tried to unite them.
Let me explain those rules:
I need to search and match and article that has the same TAG related to it inside the same project (as CampanhaId)
I need to search and match the same TAG without be inside the same project, but public articles
Recent articles at the same project
Recent public article
I need to follow these rules in priory and search for first three articles passing by then.
So, if first rule hasn't at least 3 articles, the second rule will try to fill it. The third and fourth rules follow the same way.
I tried to create a query like this:
CREATE PROCEDURE [dbo].[SP_GetNoticiaRelacionada]
(#Tag VARCHAR(50), #ExtranetId INT, #CampanhaAreaId INT, #NoticiaId INT)
AS
BEGIN
SELECT TOP 3 *
FROM
(SELECT DISTINCT
ArtigoId, CategoriaId, Titulo, Conteudo,
Subtitulo, Categoria, FotoCompacta, QtdResposta,
0 AS MATCH, DataAlteracao
FROM
(SELECT
A.ArtigoId, A.CategoriaId, A.Titulo, A.Conteudo,
A.Subtitulo, C.Nome AS Categoria,
A.ImgAlt AS FotoCompacta,
(SELECT COUNT(*) FROM Comentario C
WHERE C.GenericAreaId = A.ArtigoId) AS QtdResposta,
1 AS MATCH, A.DataAlteracao
FROM
Artigo A
JOIN
ArtigoCategoria C ON A.CategoriaId = C.CategoriaId
WHERE
A.Apagado = 0
AND A.TAG COLLATE Latin1_General_CI_AI LIKE '%' + #Tag + '%'
AND A.CampanhaAreaId = #CampanhaAreaId
AND A.ArtigoId <> #NoticiaId
UNION
SELECT A.ArtigoId
,A.CategoriaId
,A.Titulo
,A.Conteudo
,A.Subtitulo
,C.Nome AS Categoria
,A.ImgAlt AS FotoCompacta
,(SELECT COUNT(*) FROM Comentario C WHERE C.GenericAreaId = A.ArtigoId) AS QtdResposta
,2 AS MATCH
,A.DataAlteracao
FROM Artigo A
JOIN ArtigoCategoria C ON A.CategoriaId = C.CategoriaId
WHERE A.Apagado = 0 AND A.TAG COLLATE Latin1_General_CI_AI LIKE '%' + #Tag + '%' AND A.CampanhaId = #ExtranetId AND A.ArtigoId <> #NoticiaId
UNION
SELECT A.ArtigoId
,A.CategoriaId
,A.Titulo
,A.Conteudo
,A.Subtitulo
,C.Nome AS Categoria
,A.ImgAlt AS FotoCompacta
,(SELECT COUNT(*) FROM Comentario C WHERE C.GenericAreaId = A.ArtigoId) AS QtdResposta
,3 AS MATCH
,A.DataAlteracao
FROM Artigo A
JOIN ArtigoCategoria C ON A.CategoriaId = C.CategoriaId
WHERE A.Apagado = 0 AND A.CampanhaAreaId = #CampanhaAreaId AND A.ArtigoId <> #NoticiaId
UNION
SELECT A.ArtigoId
,A.CategoriaId
,A.Titulo
,A.Conteudo
,A.Subtitulo
,C.Nome AS Categoria
,A.ImgAlt AS FotoCompacta
,(SELECT COUNT(*) FROM Comentario C WHERE C.GenericAreaId = A.ArtigoId) AS QtdResposta
,4 AS MATCH
,A.DataAlteracao
FROM Artigo A
JOIN ArtigoCategoria C ON A.CategoriaId = C.CategoriaId
WHERE A.Apagado = 0 AND A.CampanhaId = #ExtranetId AND A.ArtigoId <> #NoticiaId
) AS T
GROUP BY
ArtigoId
,CategoriaId
,Titulo
,Conteudo
,Subtitulo
,Categoria
,FotoCompacta
,QtdResposta
,MATCH
,DataAlteracao) AS T2
ORDER BY T2.MATCH ASC, T2.DataAlteracao DESC
END
So, the first query returns only Articles in the same TAG and Project.
The second one, returns all Articles with matching the same TAG.
The third one, matches all Article in the same Project.
The last one matches all Article published.
My real problem, I guess, all the results don't respect that order.
If I have two articles with the same TAG, this should bring first as related articles, but somehow this brings first any article that I updated recently and should not be the first one in the list.
When I tried to execute this procedure, SQL Server always returns the column Match with a value of 0.
I think the problem is inside this Match column that I cannot order by it.
If someone needs more information, please advise me. I'll be appreciate any help.
I don't have any further actions I need to take.
You are doing "SELECT 0 AS MATCH" in your outer query, which means it is over-writing any values in your inner query.
In other words, to expose the issue, your code could be simplified to this:
SELECT 0 AS Match
FROM (
SELECT 1 AS Match
UNION
SELECT 2 AS Match
UNION
SELECT 3 AS Match
UNION
SELECT 4 AS Match
)
ORDER BY Match
Since you are using Match 1-4 in the inner query, but then stating "SELECT 0 AS Match" in the outer query that selects from the inner query, all the rows are going to have 0 for Match.
Instead of getting "0 AS Match" in the outer query, you should just get Match from the inner query.

Append Table Name to Field Name with Select *

Sorry if this is a duplicate. I have searched but only find aliasing fields and tables.
I have a query:
SELECT *
FROM MyTable1 ca LEFT OUTER JOIN MyTable2 dcn ON dcn.dstrct_code = ca.dstrct_code
LEFT OUTER JOIN MyTable2 cdn ON cdn.dstrct_code = ca.cost_dstrct_cde
LEFT OUTER JOIN MyTable3 bb ON bb.supplier_code = ca.supplier_code
WHERE ca.dstrct_code = '0001'
AND ca.req_232_type = 'P'
AND ca.requisition_no = '264982 000'
AND ca.alloc_count = '01'
ORDER BY ca.alloc_count ASC
Please dont shoot me down for using * im not done with the query yet. If I execute this query I get a row of data however the tables I am selecting from all have a good number of fields and many are simularly named. So my question is... Is there anyway to select * from and append the table name to the field name so it is more obvious which field belongs to which table?
I don't think there's a way to do that directly but you can do this instead. Run a query like this:
SELECT
(case t.name when 'MyTable1' then 'ca' when 'MyTable2' then 'dcn' when 'MyTable3' then 'cdn' when 'MyTable4' then 'bb' end)
+ '.' + c.name
+ ' AS "' + t.name + '.' + c.name + '",'
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE t.name in ('MyTable1', 'MyTable2', 'MyTable3', 'MyTable4')
ORDER BY t.name
Run it, preferably with results to Text (Ctrl+T), and use the results instead of the * in your original query. You have to manually remove the comma from the last line.
If you like the approach, you could streamline the process with some dynamic SQL.

Use stored procedure in Select query

I have a stored procedure that I want to use in a SELECT like below but I get an error.
The stored procedure's output is a table with one column of type int
select * from users where resCode in (EXEC getUserResselers 1)
-- stored procedure
create procedure getUserResselers
#userCode int
as
;WITH Directories AS (SELECT code FROM Resseler WHERE code =(select resselerCode from Users where code=#userCode)
UNION ALL SELECT d.code FROM Resseler d INNER JOIN Directories p ON d.parent = p.code)
SELECT * FROM Directories d
Direct selection from a stored procedure is not supported. However, this type of operation is a good candidate for a table-valued user-defined function, which might look something like:
Note that you have misspelled "resellers". I've left the misspelling so that you could test with your existing schema.
CREATE FUNCTION getUserResselers
(
#UserCode INT
)
RETURNS TABLE AS
RETURN(
WITH Directories AS (
SELECT code FROM Reseller WHERE code = (select resselerCode from Users where code=#userCode)
UNION ALL SELECT d.code FROM Resseler d INNER JOIN Directories p ON d.parent = p.code
)
SELECT * FROM Directories
)
You could then include a join to the function in your query, or you could continue to use IN, which should be something like:
select * from users where resCode in (SELECT Code FROM getUserResselers(1));