sp_executesql or execute without variables - sql-server

Id like to execute this query on sql server 2012 without using variables:
DECLARE #query VARCHAR(4000)
set #query= concat('select * from customer where id in (',
(select id from customer where comid=1 and code='30.00.0000'),
') order by code')
execute #query
So I tried this:
sp_executesql N'
select concat(''select * from customer where id in ('',
(select id from customer where comid=1 and code=''30.00.0000''),
'') order by code'')'
with no effect as it produces the query instead of returning the values.
Above version is cropped. This is whole script:
DECLARE #query VARCHAR(4000)`
DECLARE #years VARCHAR(2000)`
SELECT #years = STUFF((
SELECT DISTINCT
'],[' + ltrim(str(etos))
FROM
(
select c.code , year(f.ftrdate) as etos , sum((it.outputvalmode-it.inputvalmode)*st.netlinevalue) as katharh
from fintrade f left join itemtrans it on it.ftrid=f.id
left join material m on m.id=it.iteid
left join storetradelines st on it.stlid=st.id
left join customer c on c.id=f.cusid
where m.code like '73.00.901%' and m.comid=1
group by c.code , year(f.ftrdate)
)a
ORDER BY '],[' + ltrim(str(etos))
FOR XML PATH('')), 1, 2, '') + ']'
SET #query =
'SELECT * FROM
(
select c.code , year(f.ftrdate) as etos , sum((it.outputvalmode-it.inputvalmode)*st.netlinevalue) as katharh
from fintrade f left join itemtrans it on it.ftrid=f.id
left join material m on m.id=it.iteid
left join storetradelines st on it.stlid=st.id
left join customer c on c.id=f.cusid
where m.code like ''73.00.901%'' and m.comid=1
group by c.code , year(f.ftrdate)
) AS t
PIVOT (MAX(katharh) FOR etos IN (' + #years + ')) AS pvt'`
print (#query)
execute (#query)

Taking your code
sp_executesql N'
select concat(''select * from sys.objects object_id id in ('',
(select object_id from sys.objects where object_id=1 and object_id=''30000000''),
'') order by object_id'')'
and removing one level of nesting (the sp_executesql) we get
select concat('select * from sys.objects object_id id in (',
(select object_id from sys.objects where object_id=1 and object_id='30000000'),
') order by object_id')
which of course outputs
select * from sys.objects object_id id in () order by object_id
as you observed.
I think you should do:
sp_executesql #query

Related

Iterate through all DBs - Get constraints in all tables

I'm trying to iterate through all databases by listing all table constraints. I've achieved the following:
DECLARE #sql nvarchar(max) = ''
SET #sql =
'
USE ?
select con.[name] as constraint_name,
schema_name(t.schema_id) + ''.'' + t.[name] as [table],
col.[name] as column_name,
con.[definition],
case when con.is_disabled = 0
then ''Active''
else ''Disabled''
end as [status]
from sys.check_constraints con
left outer join sys.objects t
on con.parent_object_id = t.object_id
left outer join sys.all_columns col
on con.parent_column_id = col.column_id
and con.parent_object_id = col.object_id
order by con.name
'
PRINT #sql
EXEC sp_MSforeachdb #sql
I would like to have the query UNION all of my results in one clean select.
Can anyone help?
Using SQL Server 2016.
One way is to insert the intermediate results into a temp table. Below is an example that also includes the database name in the results.
CREATE TABLE #results (
[database_name] sysname
,[constraint_name] nvarchar(128)
,[table] nvarchar(257)
,[column_name] nvarchar(128)
,[definition] nvarchar(max)
,[status] varchar(8)
);
DECLARE #sql nvarchar(max) = ''
SET #sql =
N'
USE [?];
INSERT INTO #results
select
N''?'' as database_name,
con.[name] as constraint_name,
schema_name(t.schema_id) + ''.'' + t.[name] as [table],
col.[name] as column_name,
con.[definition],
case when con.is_disabled = 0
then ''Active''
else ''Disabled''
end as [status]
from sys.check_constraints con
left outer join sys.objects t
on con.parent_object_id = t.object_id
left outer join sys.all_columns col
on con.parent_column_id = col.column_id
and con.parent_object_id = col.object_id;
';
PRINT #sql;
EXEC sp_MSforeachdb #sql;
SELECT * FROM #results;

List all tables used in a SQL statement

Currently i have to create a list of all tables & schemes used in several (terribly) long SQL statements.
Of course i could go manually through the SQL statements and write down every table used in a JOIN, Subselect and so on.
But i'd be curious if there is any easier way to do it. maybe with a "simple" SQL statement, but i have no clue how to do it.
Why am i asking? I'd have to do this for about 50 SQL-Unload-Statements, where all of them use between 30 and 70 tables. I guess you can imagine this quite boring work
Thanks in advance for any input & hints!
Have a read here: How can i get the list of tables in the stored procedure
;WITH stored_procedures AS (
SELECT
o.name AS proc_name, oo.name AS table_name,
ROW_NUMBER() OVER(partition by o.name,oo.name ORDER BY o.name,oo.name) AS row
FROM sysdepends d
INNER JOIN sysobjects o ON o.id=d.id
INNER JOIN sysobjects oo ON oo.id=d.depid
WHERE o.xtype = 'P')
SELECT proc_name, table_name FROM stored_procedures
WHERE row = 1
ORDER BY proc_name,table_name
All credit to the OP of the code above in the thread above.
I will post this answer & mark it as solved, as it was the best and easiest way to solve my issue.
Hint was in a comment by #whereisSQL (thanks a lot!)
Seems like it was already asked in this thread, but i didn't find it:
https://dba.stackexchange.com/questions/121346/need-to-get-identify-all-tables-and-columns-in-a-sql-query/121355#121355
There is an online "get table column" tool to list the tables of a SQL statement here:
http://107.170.101.241:8080/getTableColumn/
It lists all tables and additionally columns used in the statement! Perfect solution in my case.
This may help. Using DMVs
IF EXISTS (
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[sp_dependsobj]')
AND type IN (
N'P'
,N'PC'
)
)
DROP PROCEDURE [dbo].[sp_dependsobj]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_dependsobj] (#Objname NVARCHAR(2000))
AS
BEGIN
SET NOCOUNT ON
DECLARE #ObjID INTEGER
DECLARE #ObjType VARCHAR(100)
DECLARE #RowCount INTEGER = 0
SELECT #ObjID = OBJECT_ID(#Objname)
SELECT #ObjType = TYPE
FROM sys.objects
WHERE object_id = #ObjID
DECLARE #RefObjects AS TABLE (
[Object_name] SYSNAME
,[Type] VARCHAR(255)
,referenced_entity_name SYSNAME
,Column_name SYSNAME NULL
,referenced_entity_type VARCHAR(255)
)
DECLARE #FoundIn AS TABLE (
[Object_name] SYSNAME
,[Found In] SYSNAME
,[Type] VARCHAR(255)
)
DECLARE #SQLStr VARCHAR(MAX)
SET #SQLStr = '
WITH CTE_Objects
AS
(
SELECT o.NAME referencing_entity_name
,o.type_desc referencing_object_type
,sed.referenced_entity_name
,refobj.referenced_minor_name
,obj.type_desc
,obj.object_id
FROM sys.sql_expression_dependencies sed
INNER JOIN sys.objects o ON sed.referencing_id = o.[object_id]
INNER JOIN sys.objects obj ON sed.referenced_entity_name = obj.name
INNER JOIN sys.dm_sql_referenced_entities(''dbo.' + #Objname + ''', ''OBJECT'') refobj ON
refobj.referenced_id = sed.referenced_id
WHERE o.NAME = ''' + #Objname + '''
UNION
SELECT ''' + #Objname + ''', (SELECT type_desc from sys.objects where name = ''' + #Objname + '''), referenced_entity_name, NULL, obj.type_desc
,obj.object_id
FROM sys.dm_sql_referenced_entities (''dbo.' + '' + #Objname +
''', ''OBJECT'') refObj INNER JOIN sys.objects obj
ON refObj.referenced_entity_name = obj.name
)
SELECT CTE.referencing_entity_name Object_name, CTE.referencing_object_type Type, CTE.referenced_entity_name, CTE.referenced_minor_name Column_name, CTE.type_desc referenced_entity_type
FROM CTE_Objects CTE LEFT JOIN sys.columns cl ON
cte.object_id = cl.object_id AND cte.referenced_minor_name = cl.name
Order by cte.referencing_entity_name, CASE WHEN cte.referencing_entity_name IS NULL THEN 0 ELSE cl.column_id END
'
INSERT INTO #RefObjects (
[Object_name]
,[Type]
,referenced_entity_name
,Column_name
,referenced_entity_type
)
EXEC (#SQLStr)
SET #RowCount = ##ROWCOUNT
IF #RowCount > 0
BEGIN
SELECT *
FROM #RefObjects
END
SET #SQLStr = '
SELECT DISTINCT [Object Name] = o.NAME
,[Found In] = sp.NAME
,sp.type_desc Type
FROM sys.objects o
INNER JOIN sys.sql_expression_dependencies sd ON o.object_id = sd.referenced_id
INNER JOIN sys.objects sp ON sd.referencing_id = sp.object_id
WHERE o.NAME = ''' + #Objname + '''
UNION
SELECT ''' + #Objname + ''', referencing_entity_name, (SELECT type_desc from sys.objects where name = referencing_entity_name)
FROM sys.dm_sql_referencing_entities (''dbo.' + '' + #Objname + ''', ''OBJECT'');
'
INSERT INTO #FoundIn (
[Object_name]
,[Found In]
,[Type]
)
EXEC (#SQLStr)
SET #RowCount = ##ROWCOUNT
IF #RowCount > 0
BEGIN
SELECT *
FROM #FoundIn
END
IF NOT EXISTS (
SELECT 1
FROM #RefObjects
)
AND NOT EXISTS (
SELECT 1
FROM #FoundIn
)
BEGIN
PRINT 'Object does not reference any object, and no objects reference it.'
END
SET NOCOUNT OFF
END
GO
The question is old, but here is a regex for those that want the tables used in SQL statement (From/join).
I created it specially for my case, but it may be adapt and useful for others:
(from|join)[ ]{1,}[^.\n\ ]+?(?=(.))[.].*?(?=( |\n))

Dynamic Gridview with Pivot Table

I am currently creating a gridview that has dynamic columns.
I have successfully created this from querying the log hours for every task per date on a specific sprint. The logged dates becomes the column and the task and logged hours become rows. With both vertical and horizontal totals.
On this gridview, you can manually edit the logged hours and it will be saved to the database.
The problem now is the design changes.
What I need to do is just list the sprint duration dates for columns and task on the first column even if there are still no logged hour on that task or date.
Any help will be appreciated. Thanks.
here is the stored procedure for this pivoted table
USE [JiraAutomation]
GO
/****** Object: StoredProcedure [dbo].[logs] Script Date: 4/12/2016 7:00:09 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[logs]
#username nvarchar(30),
#sprintId nvarchar(30)
AS
/* COLUMNS HEADERS */
Declare
#cols as NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(log_date)
from tbl_log join tbl_task on tbl_task.task_id = tbl_log.task_id
where tbl_log.username = #username
and tbl_log.sprint_id = #sprintId
group by log_date
order by log_date
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
DECLARE #horiz_total nvarchar(MAX)
SELECT #horiz_total = stuff((
SELECT '+isnull(' + quotename(log_date) + ',0)'
FROM tbl_log
join tbl_task on tbl_task.task_id = tbl_log.task_id
where tbl_log.username = #username
and tbl_log.sprint_id = #sprintId
GROUP BY log_date
ORDER BY log_date
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'),1,1,'')
DECLARE #vert_total nvarchar(MAX)
SELECT #vert_total = stuff((
SELECT ',sum(' + quotename(log_date) + ')'
FROM tbl_log
join tbl_task on tbl_task.task_id = tbl_log.task_id
where tbl_log.username = #username
and tbl_log.sprint_id = #sprintId
GROUP BY log_date
ORDER BY log_date
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'),1,1,'')
DECLARE #isnulls nvarchar(MAX)
SELECT #isnulls = stuff((
SELECT ',isnull(' + quotename(log_date) + ',0) as '+quotename(log_date)
FROM tbl_log
GROUP BY log_date
ORDER BY log_date
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'),1,1,'')
DECLARE #query nvarchar(MAX)
SET #query = 'select task_description as TASK,' + #cols + ',' + #horiz_total + ' as Total
into #tmp_result
from (select task_description, log_date, log_hours from tbl_log join tbl_task on tbl_task.task_id = tbl_log.task_id
where tbl_log.username = '''+#username+'''
and tbl_log.sprint_id = '''+#sprintId+'''
) x
pivot (sum(log_hours) for log_date in (' + #cols + ')) p
select *
from #tmp_result
union all
SELECT '''','+#vert_total +',
ISNULL (SUM([Total]),0) FROM #tmp_result
DROP TABLE #tmp_result'
-- PRINT 'Pivot Query '+#FinalQuery
EXECUTE(#query)
If I understand the issue correctly, then the issue is with the type of join in your query in the #query variable
'select task_description as TASK,' + #cols + ',' + #horiz_total + ' as Total
into #tmp_result
from (select task_description, log_date, log_hours from tbl_log join tbl_task on tbl_task.task_id = tbl_log.task_id
where tbl_log.username = '''+#username+'''
and tbl_log.sprint_id = '''+#sprintId+'''
The JOIN is exclusive, so if there is no tasks it will exclude the records in the tbl_log.
To display the values from tbl_log regardless of havng corresponding records in tbl_task the join should be changed to inclusive, in your case this should be a LEFT OUTER JOIN
so the code should look like
'select task_description as TASK,' + #cols + ',' + #horiz_total + ' as Total
into #tmp_result
from (select task_description, log_date, log_hours from tbl_log LEFT OUTER JOIN tbl_task on tbl_task.task_id = tbl_log.task_id
where tbl_log.username = '''+#username+'''
and tbl_log.sprint_id = '''+#sprintId+'''
You can omit the OUTER from LEFT OUTER JOIN
here is a link to nice explanation of different types of joins
SQL JOIN and different types of JOINs
I hope this helps.

SQl server Dynamic query

I have a table Connection
KEY Base_TBL Connected_table Base_tbl_colmn Connected_table_colmn
---- ------ ------------- ------------ ------------------
PRM Table1 Table2,Table3 colm1 Colm2,colm3
FRN Table4 table5 colm4 colm5
I need to generate a dynamic Query which should give an output something like this
select * from table1
INNER JOIN Table 2
ON table1.colm1 =table2.colm2
INNER JOIN Table3
on Table1.colm1=tabl3.colm3
number of tables in Connected_table can be anything and i have to join on the basis of that.
I have tried REPLACE Function within The dynamic query but not getting the desired result.
CREATE PROCEDURE [dbo].jointables
[Key] nvarchar(10)
AS
BEGIN
SET NOCOUNT ON
SET ROWCOUNT 0
DECLARE #sql as nvarchar(4000)
select #sql= 'select * from '+ Base_TBL + 'inner join ' +
Please guide me how to proceed further
CREATE FUNCTION [dbo].[FN_SPLIT](#Long_str varchar(max),#split_str varchar(100))
RETURNS #tmp TABLE(
ID inT IDENTITY PRIMARY KEY,
SPLIT varchar(max)
)
AS
BEGIN
DECLARE #sxml XML
SET #sxml='<root><node>'+REPLACE(#Long_str,#split_str,'</node><node>')+'</node></root>'
INSERT INTO #tmp([SPLIT])
SELECT b.value('.','varchar(max)') FROM #sxml.nodes('root/node') AS s(b)
RETURN
END
GO
DECLARE #sql as nvarchar(4000)
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
;WITH testdata AS
(
select 'PRM' AS [Key],'Table1' AS Base_TBL,'Table2,Table3' AS Connected_table,'colm1' AS Base_tbl_colmn,'Colm2,colm3' AS Connected_table_colmn
)
SELECT * INTO #temp FROM testdata
select #sql= 'select * from '+ Base_TBL +' ' +t.joinstring
FROM #temp
CROSS APPLY (
SELECT STUFF((
SELECT ' INNER JOIN '+ ft.[SPLIT] + ' ON ' + Base_TBL+'.'+Base_tbl_colmn +'='+ft.[SPLIT]+'.'+fc.[SPLIT]
FROM
dbo.FN_SPLIT(Connected_table,',') AS ft
INNER JOIN dbo.FN_SPLIT(Connected_table_colmn,',') AS fc ON fc.ID=ft.ID
FOR XML PATH('')),1,1,'') AS joinstring
) AS t
SELECT #sql
Below example just process one line
when process multiple lines, you can use another stuff function combine multiple lines
SELECT STUFF((
select ' select * from '+ Base_TBL +' ' +t.joinstring
FROM #temp
CROSS APPLY (
SELECT STUFF((
SELECT ' INNER JOIN '+ ft.[SPLIT] + ' ON ' + Base_TBL+'.'+Base_tbl_colmn +'='+ft.[SPLIT]+'.'+fc.[SPLIT]
FROM
dbo.FN_SPLIT(Connected_table,',') AS ft
INNER JOIN dbo.FN_SPLIT(Connected_table_colmn,',') AS fc ON fc.ID=ft.ID
FOR XML PATH('')),1,1,'') AS joinstring
) AS t FOR XML PATH('')
),1,1,'')

how to get all stored procedure execution time , cup time etc

SELECT DB_NAME(st.dbid) DBName
,OBJECT_SCHEMA_NAME(objectid,st.dbid) SchemaName
,OBJECT_NAME(objectid,st.dbid) StoredProcedure
,max(cp.usecounts) execution_count
,sum(qs.total_elapsed_time) total_elapsed_time
,sum(qs.total_elapsed_time) / max(cp.usecounts) avg_elapsed_time
FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.plan_handle) st
join sys.dm_exec_cached_plans cp on qs.plan_handle = cp.plan_handle
where cp.objtype = 'proc'
group by DB_NAME(st.dbid),OBJECT_SCHEMA_NAME(objectid,st.dbid), OBJECT_NAME(objectid,st.dbid)
order by sum(qs.total_elapsed_time) desc
I am running above query but not able to find all SP list details which are created in database.
It shows only fewer SP.
Please help me.
Waiting for your valuable reply.
You could try something like this, a lot more complicated but it gets around the fact that not every stored procedure will have statistics:
CREATE TABLE #x(
database_id INT,
DatabaseName SYSNAME,
SchemaName SYSNAME,
ProcedureName SYSNAME,
[object_id] INT);
DECLARE #sql NVARCHAR(MAX) = '';
SELECT
#sql = #sql + N'INSERT INTO #x SELECT ' + CONVERT(VARCHAR(50), d.database_id) + ', ''' + name + ''', s.name, p.name, p.[object_id]
FROM ' + QUOTENAME(d.name) + '.sys.schemas AS s
INNER JOIN ' + QUOTENAME(d.name) + '.sys.procedures AS p ON p.schema_id = s.schema_id;' FROM sys.databases d WHERE d.database_id > 4;
EXEC sp_executesql #sql;
WITH PlanData AS (
SELECT
st.[dbid] AS database_id,
st.objectid AS [object_id],
DB_NAME(st.[dbid]) AS DBName,
OBJECT_SCHEMA_NAME(st.objectid, st.[dbid]) AS SchemaName,
OBJECT_NAME(st.objectid, st.[dbid]) AS StoredProcedure,
MAX(cp.usecounts) AS execution_count,
SUM(qs.total_elapsed_time) AS total_elapsed_time,
SUM(qs.total_elapsed_time) / MAX(cp.usecounts) AS avg_elapsed_time
FROM
sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.plan_handle) st
LEFT JOIN sys.dm_exec_cached_plans cp on cp.plan_handle = qs.plan_handle
WHERE
cp.objtype = 'PROC'
GROUP BY
st.[dbid],
st.objectid,
DB_NAME(st.[dbid]),
OBJECT_SCHEMA_NAME(st.objectid, st.[dbid]),
OBJECT_NAME(st.objectid, st.[dbid]))
SELECT
x.DatabaseName,
x.SchemaName,
x.ProcedureName,
pd.execution_count,
pd.total_elapsed_time,
pd.avg_elapsed_time
FROM
#x x
LEFT JOIN PlanData pd ON pd.database_id = x.database_id AND pd.[object_id] = x.[object_id];
DROP TABLE #x;
From MSDN regarding sys.dm_exec_query_stats, "The view contains one row per query statement within the cached plan, and the lifetime of the rows are tied to the plan itself. When a plan is removed from the cache, the corresponding rows are eliminated from this view."

Resources