SQL SERVER QUERY EXEC sp_helptext - sql

I want to use EXEC sp_helptext for each stored procedure in the database.
So I would like to use EXEC sp_stored_procedures and retrieve the PROCEDURE_NAME from it to execute : EXEC sp_helptext PROCEDURE_NAME in loop.
Any help would be deeply appreciated.

No need to call sp_helptext per proc, you can get them all in a single query:
select sm.definition
from sys.sql_modules sm
inner join sys.objects o on o.object_id = sm.object_id
where o.type = 'P'

select 'PRINT ''SET QUOTED_IDENTIFIER ' + case uses_quoted_identifier when 1 then 'ON''' else 'OFF' + '''' end + char(13) + char(10)
+ 'PRINT ''GO ''' + char(13) + char(10)
+ 'PRINT ''SET ANSI_NULLS ' + case uses_ansi_nulls when 1 then 'ON''' else 'OFF' + '''' end + char(13) + char(10)
+ 'PRINT ''GO ''' + char(13) + char(10)
+ 'GO'
+ char(13) + char(10) + 'sp_helptext ' + o.name + char(13) + char(10) + 'GO' + char(13) + char(10)
+ 'PRINT ''GO ''' + char(13) + char(10)
FROM sys.all_sql_modules AS m
JOIN sys.all_objects AS o
ON m.Object_ID = o.Object_ID
JOIN sys.schemas AS s
ON o.schema_id = s.schema_id
WHERE o.is_ms_shipped=0
------------------------------------------------------
-- custom filters below
------------------------------------------------------
and o.type = 'SP'
So all of that other stuff in the beginning is because sp_helptext doesn't also have whether or not ansi nulls or quoted identifiers were set to anything in particular. This script will create a script that can hopefully be run for your needs.

Related

Force the output query to shows the DB_NAME() data once

I've got a query that selects all indexes from a table and generate an output text to drop them individually.
I want to put the DB_NAME() info in the beginning of command for once, but at this moment the data is showed at every index drop.
I've tried to put a select before, but without success.
Could someone help me? Query and results are below:
- QUERY
SELECT
'USE ' + QUOTENAME(db_name()) + ';' + CHAR(13) +
'GO ' + CHAR(13) +
'DROP INDEX ' + QUOTENAME(i.name) + ' ON ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.Name) + ';' + CHAR(13) +
'GO'
FROM
sys.indexes i
JOIN sys.tables t ON t.object_id = i.object_id
JOIN sys.schemas s ON s.schema_id = t.schema_id
WHERE
t.Name = 'Queue';
- Results that I get (example)
USE [master];
GO
DROP INDEX [PK_Queue] ON [dbo].[Queue];
GO
USE [master];
GO
DROP INDEX [I_001] ON [dbo].[Queue];
GO
USE [master];
GO
DROP INDEX [I_002] ON [dbo].[Queue];
GO
- Results that I want
USE [master];
GO
DROP INDEX [PK_Queue] ON [dbo].[Queue];
GO
DROP INDEX [I_001] ON [dbo].[Queue];
GO
DROP INDEX [I_002] ON [dbo].[Queue];
GO
You can just initialize a variable with the USE command, and then append the DROP INDEX commands using string concatenation. This is easier in SQL Server 2017 (STRING_AGG()), but you didn't tell us what version you use, so...
DECLARE #sql nvarchar(max) = N'USE ' + QUOTENAME(db_name()) + ';';
SELECT #sql += char(13) + N'GO' + char(13) + N'DROP INDEX '
+ QUOTENAME(i.name) + ' ON ' + QUOTENAME(s.name)
+ '.' + QUOTENAME(t.name) + ';' + CHAR(13)
FROM
sys.indexes i
JOIN sys.tables t ON t.object_id = i.object_id
JOIN sys.schemas s ON s.schema_id = t.schema_id
WHERE
t.Name = 'Queue' AND i.name IS NOT NULL;
PRINT #sql;
Example db<>fiddle
SELECT Txt
from
(
SELECT
1 as Seq,
'USE ' + QUOTENAME(db_name()) + ';' + CHAR(13) +
'GO ' + CHAR(13) as Txt
union all
SELECT
2 as Seq,
'DROP INDEX ' + QUOTENAME(i.name) + ' ON ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.Name) + ';' + CHAR(13) +
'GO'
FROM
sys.indexes i
JOIN sys.tables t ON t.object_id = i.object_id
JOIN sys.schemas s ON s.schema_id = t.schema_id
WHERE
t.Name = 'Queue'
) S1
order by Seq
But, why bother? You can script almost everything in SQL Server Management Studio as #shreepat18 said!

Put single quotes into single quotes in SQL Server string

I have the update query below.
update tableName
set columnName = null
where isnull(columnName, '') = ''
I want to put single quotes in a SQL Server string builder query so that the above query can be executed for every column in the table. See this query:
Declare #sql2 varchar(max) = ''
declare #tablename2 as varchar(255) = 'test2'
select #sql2 = #sql2 + 'update [' + #tablename2 + '] set [' + c.name +']' + ' = NULL ' +
' WHERE ISNULL([' + c.name + '], ' + '' + ') = ' + ''
from sys.columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = #tablename2
EXEC (#sql2)
go
Below is test data.
create table test2
(
test varchar(50)
)
insert into test2
values (' ewewwe'), ('sdsddsds '), ('')
I get this error while executing the SQL String builder query:
Incorrect syntax near ') = '
What am I doing wrong?
The error you receive is because the statement string is not valid. You end up with an unescaped string.
You need to add an escaped quote ('') for each quote you need, ('''''') like this:
Declare #sql2 varchar(max) =''
declare #tablename2 as varchar(255) ='test2'
select #sql2 = #sql2 + 'update [' + #tablename2 + '] set [' + c.name + ']' + ' = NULL ' +
' WHERE ISNULL([' + c.name + '], ' + '''''' + ') = ' + ''''''
from sys.columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = #tablename2
EXEC (#sql2)
go
when you use isnull, you have to provide 2 parameters
' WHERE ISNULL([' + c.name + '], ' + '???' + ') = ' + ''
You need to provide something for the ??? and currently its empty
Replace with
WHERE ISNULL([' + c.name + '], ' + '''''' + ')
Single quotes are self-escaped; that is, you put two together in a literal to get one in the final string.
Additionally, you want the QUOTENAME() function to handle enclosing these fields. It's smart enough to also account for names that might include braces or other weirdness, plus you can expect it to be updated if anything else is ever added to the language that might interfere:
DECLARE #sql2 varchar(max) = ''
DECLARE #tablename2 as varchar(255) = 'test2'
SELECT #sql2 = #sql2 +
'update ' + QUOTENAME(#tablename2) +
' set ' + QUOTENAME(c.name) + ' = NULL' +
' WHERE COALESCE(RTRIM(' + QUOTENAME(c.name) + '), '''') = '''' '
FROM sys.columns c
INNER JOIN sys.tables t on c.object_id = t.object_id
WHERE t.name = #tablename2
EXEC(#sql2)

A SELECT INTO statement cannot contain a SELECT statement that assigns values to a variable

I am trying to create a stored procedure or function to find the number of null values in each column in a table.
I am having problems determining the syntax for converting the code to a stored procedure/function.
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = (
SELECT '
' +
STUFF((
SELECT ', [' + c.name + '] = ' + CASE WHEN c.is_nullable = 0 THEN '0' ELSE 'COUNT(*) - COUNT([' + c.name + '])' END
FROM sys.columns c
WHERE c.[object_id] = o.[object_id]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, 'SELECT ''' + SCHEMA_NAME(o.[schema_id]) + '.' + o.name + ''', COUNT(*), ') + '
FROM [' + SCHEMA_NAME(o.[schema_id]) + '].[' + o.name + ']'
FROM sys.objects o
WHERE o.[type] = 'U'
AND o.is_ms_shipped = 0
AND [name] = 'BSEG'
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
INTO xzy
PRINT #SQL
EXEC sys.sp_executesql #SQL
I want to stored the results in a table. But I am getting the following error message:
Msg 194, Level 15, State 1, Line 2
A SELECT INTO statement cannot contain a SELECT statement that assigns values to a variable.
So my ultimate aim is to have a stored procedure/function which upon execution will give number of null values in each column in a table and the results will be stored in another result table.
Can you please check with this following changes-
Remove assigning part from your query and just use the simple select statement as-
SELECT '' +
STUFF((
...
--Note: Write the SQL in such way so that only SQL
--text from STUFF functions is returned. There is no
--requirement of assigning the text first to variable #SQL
Add INSERT before INTO key as below-
...
INSERT INTO xzy
...
If still no luck, please provide output of PRINT #SQL command with above 2 changes.
The "INTO xyz" should go above "FROM sys.objects o"?
EDIT
Try this
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = (
SELECT '
' +
STUFF((
SELECT ', ' + CASE WHEN c.is_nullable = 0 THEN '0' ELSE 'COUNT(*) - COUNT([' + c.name + '])' END + ' AS [' + c.name + ']'
FROM sys.columns c
WHERE c.[object_id] = o.[object_id]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, 'SELECT ''' + SCHEMA_NAME(o.[schema_id]) + '.' + o.name + ''' as TableName, COUNT(*) as Cnt, ') + '
INTO xzy
FROM [' + SCHEMA_NAME(o.[schema_id]) + '].[' + o.name + ']'
FROM sys.objects o
WHERE o.[type] = 'U'
AND o.is_ms_shipped = 0
AND [name] = 'BSEG'
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
PRINT #SQL
EXEC sys.sp_executesql #SQL

sp_MSforeachtable Abuse (Modification needed)

Recently someone hacked into our database using sp_MSforeachtable, so multiline query if im right.
Now my question is how i can modify sys.sp_MSforeachtable, he is using #command1 and other commands to execute a query in order to drop our tables.
XXXX=Censored db name
(Somehow also spaces in front of the USE)
USE XXXX;
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all";
EXEC sp_MSforeachtable #command1 = "DROP TABLE ?"
Then my SQL Profiler shows:
select #mscat = ltrim(str(convert(int, 0x0002)))
exec(N'declare hCForEachTable cursor global for select ''['' + REPLACE(schema_name(syso.schema_id), N'']'', N'']]'') + '']'' + ''.'' + ''['' + REPLACE(object_name(o.id), N'']'', N'']]'') + '']'' from dbo.sysobjects o join sys.all_objects syso on o.id = syso.object_id '
+ N' where OBJECTPROPERTY(o.id, N''IsUserTable'') = 1 ' + N' and o.category & ' + #mscat + N' = 0 '
+ #whereand)
declare hCForEachTable cursor global for select '[' + REPLACE(schema_name(syso.schema_id), N']', N']]') + ']' + '.' + '[' + REPLACE(object_name(o.id), N']', N']]') + ']' from dbo.sysobjects o join sys.all_objects syso on o.id = syso.object_id where OBJECTPROPERTY(o.id, N'IsUserTable') = 1 and o.category & 2 = 0
exec #retval = sys.sp_MSforeach_worker #command1, #replacechar, #command2, #command3, 0
create table #qtemp ( /* Temp command storage */
qnum int NOT NULL,
qchar nvarchar(2000) COLLATE database_default NULL
)
Could anyone let me know how to secure these things? SQL Profiler is showing me the application name is PHP5, so probably register page or login panel injection..

How to select object_definition(object_id) for table in sql using C#?

I have 2 question.
This query is for display script store procedure as create to query
Query :
Select object_definition(object_id) from sys.objects
where type_desc in ( 'SQL_STORED_PROCEDURE')
I can display script of all store procedure.
Question 1 : I have TestStoreProcedure in store procedures.How can I display for only TestStoreProcedure.How can I use like this :
Select object_definition(object_id) from sys.objects
where type_desc in ( 'SQL_STORED_PROCEDURE') and ??? =TestStoreProcedure
Question 2 : How can I use this query for tables or for defined table ?
I solved for tables(create script of defined table name)
declare #vsSQL varchar(8000)
declare #vsTableName varchar(50)
select #vsTableName = 'tblLocation'
select #vsSQL = 'CREATE TABLE ' + #vsTableName + char(10) + '(' + char(10)
select #vsSQL = #vsSQL + ' ' + sc.Name + ' ' + st.Name +
case when st.Name in ('varchar','varchar','char','nchar') then
'(' + cast(sc.Length as varchar) + ') ' else ' ' end +
case when sc.IsNullable = 1 then 'NULL' else 'NOT NULL' end + ',' + char(10)
from sysobjects so
join syscolumns sc on sc.id = so.id
join systypes st on st.xusertype = sc.xusertype
where so.name = #vsTableName
order by
sc.ColID
select substring(#vsSQL,1,len(#vsSQL) - 2) + char(10) + ')'
Just for completeness, to restrict the output of OBJECT_DEFINITION you would do
SELECT OBJECT_DEFINITION(object_id) From sys.objects where name='TestStoredProcedure'
EXECUTE sp_helptext proc_name --<-- Without schema name