Querying all views in SQL Server 2012 database instance - tsql

I am having a problem where the query below is only selecting the views from the current database I am connected to and not all. Is there anyway to do this and not use sp_MSForEachDB?
DECLARE #useText VARCHAR(500)
DECLARE #viewNM VARCHAR(500)
DECLARE #schemaNM VARCHAR(500)
DECLARE #dbNM VARCHAR(500)
DECLARE #sqlCmd varchar(4000)
DECLARE DBCursor CURSOR GLOBAL FOR
SELECT NAME FROM SYS.DATABASES
OPEN DBCursor
FETCH NEXT FROM DBCursor INTO #dbNM
WHILE ##FETCH_STATUS <> -1
BEGIN
SET #useText = 'USE [' + #dbNM + ']'
EXEC(#useText)
DECLARE ViewCursor CURSOR FOR
SELECT 'GRANT SELECT ON ' + '[' + SCHEMA_NAME(schema_id) + '].[' + name + ']' + ' TO [account]'
FROM SYS.VIEWS V
OPEN ViewCursor
FETCH NEXT FROM ViewCursor INTO #sqlCmd
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT(#sqlCmd)
FETCH NEXT FROM ViewCursor INTO #sqlCmd
END
CLOSE ViewCursor
DEALLOCATE ViewCursor
FETCH NEXT FROM DBCursor INTO #dbNM
END
CLOSE DBCursor
DEALLOCATE DBCursor

When EXEC statement executes a string, the string is executed as its own self-contained batch. So, the USE dbname does not affect the query outside of the EXEC.
I build a query statement like this, SELECT 'GRANT SELECT ON [' + SCHEMA_NAME(schema_id) + '].[' + name + '] TO [account]' FROM [master].SYS.VIEWS V; where the database name is inserted before the SYS.VIEWS.
See below:
DECLARE #useText VARCHAR(500)
DECLARE #viewNM VARCHAR(500)
DECLARE #schemaNM VARCHAR(500)
DECLARE #dbNM VARCHAR(500)
DECLARE #sqlCmd varchar(4000)
DECLARE DBCursor CURSOR GLOBAL FOR
SELECT NAME FROM SYS.DATABASES
OPEN DBCursor
FETCH NEXT FROM DBCursor INTO #dbNM
WHILE ##FETCH_STATUS <> -1
BEGIN
set #sqlCmd = 'SELECT ''GRANT SELECT ON ['' + SCHEMA_NAME(schema_id) + ''].['' + name + ''] TO [account]'' FROM [' + #dbNM + '].SYS.VIEWS V;'
exec( #sqlCmd );
FETCH NEXT FROM DBCursor INTO #dbNM
END
CLOSE DBCursor
DEALLOCATE DBCursor
EDIT:
You could append a USE in front of the GRANT.
set #sqlCmd = 'SELECT ''USE ' + #dbNM + '; GRANT SELECT ON ['' + SCHEMA_NAME(schema_id) + ''].['' + name + ''] TO [account]'' FROM [' + #dbNM + '].SYS.VIEWS V;'

Related

Using a Cursor to Create Triggers for all tables in a database

I am using SQL Server 2005
I am trying to create a trigger for each table contained within a database and keep getting an error which I do not understand and can not fix
If anyone has an idea of why I am getting this error or how I can resolve it that would be brilliant.
DECLARE #TableName AS VARCHAR(100)
DECLARE #audit_action as varchar(100)
DECLARE RDS_cusor CURSOR FOR
SELECT TABLE_NAME FROM [RawDataStorage].INFORMATION_SCHEMA.Tables WHERE TABLE_NAME LIKE 't_%' AND TABLE_NAME NOT LIKE 'tbl_%'
OPEN RDS_cursor
FETCH NEXT FROM RDS_cursor INTO #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
CREATE TRIGGER dbo.After_Insert_Trig
ON [dbo].[t_Agent]
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO RawDataStorage_Audit
(TableName,Audit_Action,Audit_Timestamp)
VALUES('TableName','audit_action',getdate());
END
GO
FETCH NEXT FROM RDS_cursor INTO #TableName
END
CLOSE RDS_cursor
DEALLOCATE RDS_cursor
This is the error I am getting:
Msg 156, Level 15, State 1, Line 15
Incorrect syntax near the keyword 'TRIGGER'.
Msg 102, Level 15, State 1, Line 26
Incorrect syntax near 'END'.
Msg 137, Level 15, State 2, Line 2
Must declare the scalar variable "#TableName".
any help would be greatly appreachiated
I managed to put this together, its a dynamic query that builds the sql to create the triggers using a cursor to grab the table names from the sysobjects.
CREATE TABLE [dbo].[RawDataStorage_Audit](
ID INT IDENTITY(1,1) NOT NULL,
TableName VARCHAR(50) NULL,
audDateLastChanged DATETIME null
)
Declare #TableName nvarchar(100)
Declare #SQL nvarchar(1000)
declare tables_cursor CURSOR FOR
select [name] from sysobjects
where xtype = 'U'
and [name] not like 'sys%'
order by [name]
Open tables_cursor
fetch next from tables_cursor into #TableName
WHILE ##FETCH_STATUS = 0
Begin
--create trigger for insert on each table
print #SQL
set #SQL = 'create trigger trg_u_'+#TableName+'_Inserted '
set #SQL = #SQL + ' on '+#TableName
set #SQL = #SQL + ' for insert '
set #SQL = #SQL + ' as '
set #SQL = #SQL + ' begin '
set #SQL = #SQL + ' insert into [dbo].[RawDataStorage_Audit] '
set #SQL = #SQL + ' select ''' + #TableName +''', getdate()'
set #SQL = #SQL + ' from inserted'
set #SQL = #SQL + ' end'
exec (#SQL)
print #SQL
fetch next from tables_cursor into #TableName
end
CLOSE tables_cursor
DEALLOCATE tables_cursor

SQL Server Exception handling in a cursor defined query

Here is the script I am using to run against all the databases on sql server but somehow the script stops when the database is in transition so all I want to do is the script needs to skip the database that is in transition and proceed with rest of the databases. Any help would be appreciated.
declare #name varchar(max)
SET #starttime = GETDATE()
Declare DB_cursor cursor for
SELECT Name
FROM sys.databases
WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb')
AND is_read_only = 0
AND is_in_standby = 0
AND state = 0
OPEN DB_cursor
FETCH NEXT FROM DB_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC(' use [' + #name + '] IF EXISTS (select name from sys.objects where name=''#Tablename'') UPDATE STATISTICS [' + #SchemaName + '].[' + #TableName +'](['+#StatsName+']) WITH FULLSCAN ')
FETCH NEXT FROM DB_cursor INTO #name
END
CLOSE DB_cursor
DEALLOCATE DB_cursor
Try:
DECLARE #sql NVARCHAR(MAX)
SET #sql = ' use [' + #name + '] IF EXISTS (select name from sys.objects where name=''#Tablename'') UPDATE STATISTICS [' + #SchemaName + '].[' + #TableName +'](['+#StatsName+']) WITH FULLSCAN ' )
EXEC sp_executesql #sql = #sql

Altering Multiple Tables at once

I'm trying to alter multiple SQL Server 2008 R2 tables at one time.
This is my code:
use DatabaseName
go
Declare #SchemaUsed varchar(20) = 'dbo'
create table #Tables
(
TableName varchar(100), Processed int
)
insert into #Tables
select top 1 table_name, 0
from INFORMATION_SCHEMA.TABLES
where TABLE_SCHEMA = #SchemaUsed
and table_type = 'Base Table'
and (TABLE_NAME like 'PM%' )
ORDER BY TABLE_NAME
DECLARE #TableName varchar(max)
DECLARE #SQL varchar(max)
WHILE EXISTS (select top 1 'x' from #Tables where Processed = 0)
BEGIN
SET #TableName = (select top 1 TableName from #Tables where Processed = 0)
Set #SQL = 'ALTER TABLE ' + #SchemaUsed + '.' + #TableName + ' ADD [identityID] bigint IDENTITY(1, 1) NOT NULL '
-- Set #SQL = '''' + #SQL + ''''
Print #SQL
EXEC #SQL;
update #Tables
set Processed = 1
where TableName = #TableName
END
drop table #Tables
I can't get this to work to save my life and get the following error:
Lookup Error - SQL Server Database Error: The name 'ALTER TABLE
dbo.PM1GTVLV ADD [identityID] bigint IDENTITY(1, 1) NOT NULL ' is not
a valid identifier.
I've also tried multiple string variations and using sp_executesql as well.
Can someone point out where I've gone wrong?
Try
DECLARE #SQL NVARCHAR(MAX);
EXEC sp_executesql #SQL;
Instead of EXEC #sql.
As an aside, this is a much more usable version of the same code IMHO:
DECLARE #SchemaUsed VARCHAR(20) = 'dbo';
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += CHAR(13) + CHAR(10) + N'ALTER TABLE '
+ QUOTENAME(#SchemaUsed) + '.'
+ QUOTENAME(name) + ' ADD [identityID]
BIGINT IDENTITY(1,1) NOT NULL;'
FROM sys.tables
WHERE SCHEMA_NAME([schema_id]) = #SchemaUsed
AND name LIKE 'PM%';
PRINT #sql;
--EXEC sp_executesql #sql;
Or even better:
DECLARE #SchemaUsed VARCHAR(20) = 'dbo';
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += CHAR(13) + CHAR(10) + N'ALTER TABLE '
+ QUOTENAME(#SchemaUsed) + '.'
+ QUOTENAME(name) + ' ADD [identityID]
BIGINT IDENTITY(1,1) NOT NULL;'
FROM sys.tables AS t
WHERE SCHEMA_NAME([schema_id]) = #SchemaUsed
AND name LIKE 'PM%'
AND NOT EXISTS (SELECT 1 FROM sys.columns AS c
WHERE [object_id] = t.[object_id]
AND c.is_identity = 1);
PRINT #sql;
--EXEC sp_executesql #sql;
To execute a character string, EXEC requires parenthesis around the string (or character variable) as shown in the BOL syntax:
EXEC (#SQL);

Trying to use a Case statement inside a cursor

I am trying to make the following work:
declare #ActTable as varchar(1000)
declare #cPK as VarChar(100)
declare #SQL as nvarchar(2000)
declare #FK as VarChar(100)
declare #FKRef as VarChar(200)
declare #TblRef as varchar (100)
create table #temp (
M2MTable varchar(50),
PK varchar (100),
FK Varchar(100),
FKRefTable Varchar(50))
insert into #temp
select 'slcdpm' , 'fcustno', '','' union all
select 'somast' , 'fsono', 'fcustno','slcdpm' union all
select 'soitem' , 'fsono,finumber', 'fsono','somast' union all
select 'sorels', 'fsono,finumber,frelease', 'fsono,finumber','soitem' union all
select 'qtmast', 'fquoteno', 'fcustno', 'slcdpm' union all
select 'qtitem' , 'fquoteno', 'fquoteno','qtmast' union all
select 'armast', 'fcinvoice','fcustno','scldpm' union all
select 'aritem','fcinvoice,fitem','fcinvoice','armast' union all
select 'apvend', 'fvendno','','' union all
select 'apmast','fvendno,fcinvoice','fvendno','apvend'union all
--select 'apitem','fvendno,fcinvoice,union all
select 'pomast','fpono','fvendno','apvend'union all
select 'poitem', 'fpono,fitemno','fpono','pomast' union all
select 'shmast', 'fshipno','fsokey','sorels' union all
select 'shitem','fshipno,fitemno','fshipno','shmast' -- union all
declare M2M_AddFK cursor for select M2MTable,FK,FKRefTable from #temp
open M2M_AddFK
fetch next from M2M_AddFK into #ActTable,#FK,#TblRef
while ##FETCH_STATUS = 0
Begin
case
when #FK <> ''then Set #SQL = N'alter table dbo.'+ #ActTable + ' ADD FOREIGN KEY (' + #FK + ') References DBO.' + #TblRef + '(' + #FK + ')'
Print #SQL
fetch next from M2M_AddFK into #ActTable,#FK,#TblRef
else
fetch next from M2M_AddFK into #ActTable,#FK,#TblRef
end
end
close M2M_AddFK
deallocate M2M_AddFK
drop table #temp
Please notice the Case statement:
case
when #FK <> ''then Set #SQL = N'alter table dbo.'+ #ActTable + ' ADD FOREIGN KEY (' + #FK + ') References DBO.' + #TblRef + '(' + #FK + ')'
Print #SQL
fetch next from M2M_AddFK into #ActTable,#FK,#TblRef
else
fetch next from M2M_AddFK into #ActTable,#FK,#TblRef
end
I simply want to create the alter table statement when there is a #FK value and to skip it if it's ''.
Can someone point me in the right direction?
You have to uase an IF ELSE statement.
Also, Formatting the code a little, will make it a LOT easier to read X-)
Replace the WHILE loop with
while ##FETCH_STATUS = 0
Begin
IF #FK <> ''
BEGIN
Set #SQL = N'alter table dbo.'+ #ActTable + ' ADD FOREIGN KEY (' + #FK + ') References DBO.' + #TblRef + '(' + #FK + ')'
Print #SQL
fetch next from M2M_AddFK into #ActTable,#FK,#TblRef
END
ELSE
BEGIN
fetch next from M2M_AddFK into #ActTable,#FK,#TblRef
end
end
So that your entire statement looks like
declare #ActTable as varchar(1000)
declare #cPK as VarChar(100)
declare #SQL as nvarchar(2000)
declare #FK as VarChar(100)
declare #FKRef as VarChar(200)
declare #TblRef as varchar (100)
create table #temp (
M2MTable varchar(50),
PK varchar (100),
FK Varchar(100),
FKRefTable Varchar(50))
insert into #temp
select 'slcdpm' , 'fcustno', '','' union all
select 'somast' , 'fsono', 'fcustno','slcdpm' union all
select 'soitem' , 'fsono,finumber', 'fsono','somast' union all
select 'sorels', 'fsono,finumber,frelease', 'fsono,finumber','soitem' union all
select 'qtmast', 'fquoteno', 'fcustno', 'slcdpm' union all
select 'qtitem' , 'fquoteno', 'fquoteno','qtmast' union all
select 'armast', 'fcinvoice','fcustno','scldpm' union all
select 'aritem','fcinvoice,fitem','fcinvoice','armast' union all
select 'apvend', 'fvendno','','' union all
select 'apmast','fvendno,fcinvoice','fvendno','apvend'union all
--select 'apitem','fvendno,fcinvoice,union all
select 'pomast','fpono','fvendno','apvend'union all
select 'poitem', 'fpono,fitemno','fpono','pomast' union all
select 'shmast', 'fshipno','fsokey','sorels' union all
select 'shitem','fshipno,fitemno','fshipno','shmast' -- union all
declare M2M_AddFK cursor for select M2MTable,FK,FKRefTable from #temp
open M2M_AddFK
fetch next from M2M_AddFK into #ActTable,#FK,#TblRef
while ##FETCH_STATUS = 0
Begin
IF #FK <> ''
BEGIN
Set #SQL = N'alter table dbo.'+ #ActTable + ' ADD FOREIGN KEY (' + #FK + ') References DBO.' + #TblRef + '(' + #FK + ')'
Print #SQL
fetch next from M2M_AddFK into #ActTable,#FK,#TblRef
END
ELSE
BEGIN
fetch next from M2M_AddFK into #ActTable,#FK,#TblRef
end
end
close M2M_AddFK
deallocate M2M_AddFK
drop table #temp

How to execute the stored procs from a dynamically generated query + sql server

I have a query that is dynamically fetching the stored proc names from all the databases.
Now I want to execute the stored procs and store the result in a temptable or table variable.
How to do that. Here is my SP so far
Declare #GetDBNames sysname
Declare #DynSql nvarchar(max)
Declare DBNames cursor for
Select '['+name+']' from master.dbo.sysdatabases
open DBNames
FETCH NEXT FROM DBNames into #GetDBNames
WHILE ##FETCH_STATUS=0
BEGIN
SET #DynSql = '
Select Specific_Catalog as Database_Name, Routine_Name as ''Stored Procedure Name''
From '+ #GetDBNames+'.Information_Schema.Routines '
EXEC (#DynSql)
FETCH NEXT FROM DBNames into #GetDBNames
END
Close DBNames
Deallocate DBNames
Please help.
Thanks in advance
Here's my soluton. Cursors are evil :)
Declare #DynSql nvarchar(max)
declare #result table ([Database_Name] nvarchar(128), [Stored Procedure Name] sysname)
SET #DynSql = ''
select #DynSql = #DynSql + '
Select SPECIFIC_CATALOG COLLATE DATABASE_DEFAULT as Database_Name, ROUTINE_NAME COLLATE DATABASE_DEFAULT as [Stored Procedure Name]
From ' + NAME + '.INFORMATION_SCHEMA.ROUTINES' + CHAR(13) + 'union all' + CHAR(13)
from master.dbo.sysdatabases
--remove last "union all"
SET #DynSql = left(#DynSql, LEN(#DynSql) - 10)
insert #result
exec sp_executesql #DynSql
select * from #result
INSERT [TableName] EXEC (#DynSql)
Note that if you introduce data you may want to use sp_ExecuteSQL, and you probably want to use [/] object-name escaping.