I have created a cursor which iterates through all the databases and displays the 1 record per database.
I would like the records to be inserted into 1 table where I can view it. The query may change which is why I don't want to create the table structure for a specific query and insert it. I wanted to use the "select into" clause but that will fail on the second time the cursor runs
DECLARE #DB_Name varchar(100)
DECLARE #Command nvarchar(200)
DECLARE database_cursor CURSOR FOR SELECT name FROM #DBNAME
OPEN database_cursor
FETCH NEXT FROM database_cursor INTO #DB_Name
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #Command = 'use [' + #DB_Name + '] Select '''+ #DB_Name + ''' ,'+
--Enter query below
'* from authentication where username like ''%clair#indicater%'' and password = ''Rohan2410'''
-- print #Command
EXEC sp_executesql #Command
FETCH NEXT FROM database_cursor INTO #DB_Name
END
CLOSE database_cursor
DEALLOCATE database_cursor
You should better use INSERT INTO ... instead of SELECT INTO, something like this:
DECLARE #DB_Name varchar(100)
DECLARE #Command nvarchar(200)
DECLARE database_cursor CURSOR FOR SELECT name FROM #DBNAME
OPEN database_cursor
FETCH NEXT FROM database_cursor INTO #DB_Name
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #Command = 'use [' + #DB_Name + ']
IF OBJECT_ID(''tempdb..##output'') IS NULL
BEGIN
SELECT NULL AS DB_Name,*
INTO ##output
FROM authentication WHERE 1=0
END
INSERT INTO ##output
Select '''+ #DB_Name + ''' ,'+
--Enter query below
'* from authentication where username like ''%clair#indicater%'' and password = ''Rohan2410'''
-- print #Command
EXEC sp_executesql #Command
FETCH NEXT FROM database_cursor INTO #DB_Name
END
CLOSE database_cursor
DEALLOCATE database_cursor
SELECT * FROM ##output
DROP TABLE ##output
Basically, on the first cursor iteration we will create an empty temp table with the correct structure. Then we just insert into that temp table.
Related
How do I get the return value from EXEC sp_executesql #OpenQry so I can check if the value exists in IF EXISTS?
DECLARE #TableName VARCHAR(25)
DECLARE #TD_QUERY NVARCHAR(MAX)
DECLARE CUR_QRY CURSOR FOR
SELECT TABLENAME FROM dbo.tbl_table
OPEN CUR_QRY
FETCH NEXT FROM CUR_QRY INTO #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #OpenQry = 'SELECT * FROM OPENQUERY(linkedserver,''SELECT TABLENAME FROM DBC.TABLES WHERE TABLEKIND=''''T'''' AND DATABASENAME=''''dbname'''' AND TABLENAME=''''' + #TableName + ''''''')'
EXEC sp_executesql #OpenQry
IF EXISTS (SELECT #OpenQry)
AND EXISTS (SELECT TableName FROM dbo.table WHERE TableName=#TableName)
FETCH NEXT FROM CUR_QRY INTO #TableName
END
CLOSE CUR_QRY
DEALLOCATE CUR_QRY
you just need put the variable that you want receive de return value before sp_executesql
try tis code and let me know if works
DECLARE #TableName VARCHAR(MAX)
DECLARE #TableNameToDrop VARCHAR(MAX) --NEW
DECLARE #TD_QUERY NVARCHAR(MAX)
DECLARE #OpenQry NVARCHAR(MAX) -- Dont forget to declare this variable
declare #sqldrop nvarchar(max)
DECLARE CUR_QRY CURSOR FOR
SELECT TABLENAME FROM dbo.tbl_table
OPEN CUR_QRY
FETCH NEXT FROM CUR_QRY INTO #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #OpenQry = 'SELECT * FROM OPENQUERY(linkedserver,''SELECT TABLENAME FROM DBC.TABLES WHERE TABLEKIND=''''T'''' AND DATABASENAME=''''dbname'''' AND TABLENAME=''''' + #TableName + ''''''')'
EXEC TableNameToDrop = sp_executesql #OpenQry
/*
IF EXISTS (SELECT #OpenQry)
AND EXISTS (SELECT TableName FROM dbo.table WHERE TableName=#TableName )
*/
--maybe you dont need check if the table name existis, jut try this
IF EXISTS (SELECT TableName FROM dbo.table WHERE TableName=#TableNameToDrop )
BEGIN
set #sqldrop = 'drop table '+ #TableNameToDrop
EXEC sp_executesql #sqldrop
END
FETCH NEXT FROM CUR_QRY INTO #TableName
END
CLOSE CUR_QRY
DEALLOCATE CUR_QRY
Regards
TableA exists in all 4 DBs, run this,
Use DB1
go
select CurrentDB=DB_NAME(), * From DB1..TableA union all
select CurrentDB=DB_NAME(), * From DB2..TableA union all
select CurrentDB=DB_NAME(), * From DB3..TableA union all
select CurrentDB=DB_NAME(), * From DB4..TableA
always got CurrentDB ='DB1'. is there a Simple way to get DB2,3,4 when the rows are pulling from non-DB1?
Trying to avoid hard code.
Create the same view in each database that returns the value of DB_NAME() as a column. Then, in the union, the each row will include the database name.
Try this
Use Master
set NOCOUNT ON;
Declare #db_name Varchar(12)
Declare #sql Varchar(1000)
Declare db_cursor CURSOR FOR
SELECT [name]
FROM sys.databases Where [name] like 'DB[123456789]'
Open db_cursor
Fetch Next FROM db_cursor INTO #db_name
if ##FETCH_STATUS = 0
begin
Select #sql = 'select ''' + #db_name + ''', * From ' + #db_name + '..TableA'
Fetch Next FROM db_cursor INTO #db_name
While ##FETCH_STATUS = 0
begin
select #sql = #sql + ' Union all select ''' +
#db_name + ''', * From ' + #db_name + '..TableA'
Fetch NEXT FROM db_cursor INTO #db_name
end
exec #sql
end
Close db_cursor
Deallocate db_cursor
Not tested, but basic idea is get all the matching db names. Build the sql statement, then exec it.
I'm trying to create a SQL Server script that applies some operations to all the tables in all the databases. I need to rename some tables if some conditions are respected, truncate the tables otherwise.
This is my script
EXEC sp_MSforeachdb
#command1 = '
IF not exists(select 1 where ''?'' in (''master'',''model'',''msdb'',''tempdb''))
EXEC [?].dbo.sp_MSforeachtable
#command1 = ''
IF(substring(&, 1, 3)=pv_ and right(&, 5) != _data and right(&, 4) != _BCK)
exec sp_RENAME & , &_BCK''
ELSE IF (right(&, 4) != _BCK)
TRUNCATE TABLE &
#replacechar = ''&'''
I got some errors but I'm new to SQL Server and I have not idea how to fix this script.
Any suggestions?
Many thanks
Here is a solution for start. It won't be quick, but it loops all tables of all databases on the server. Inside in the second cursor you can deceide what to do with the table.
(The query is not optimalized, just a quick solution)
DECLARE #DBName NVARCHAR(50)
DECLARE #TableName NVARCHAR(100)
DECLARE #DynamicSQL NVARCHAR(300)
DECLARE #DBCursor CURSOR
SET #DBCursor = CURSOR FOR
SELECT NAME FROM SYS.DATABASES
WHERE NAME NOT IN ('master','tempdb','model','msdb')
OPEN #DBCursor
FETCH NEXT FROM #DBCursor INTO #DBName
WHILE ##FETCH_STATUS = 0
BEGIN
CREATE TABLE #TempTableDatas
(
name varchar(100),
objectID int
)
SET #DynamicSQL = 'INSERT INTO #TempTableDatas
SELECT name, object_id FROM [' + #DBName + ']' + '.sys.Tables '
EXEC SP_EXECUTESQL #DynamicSQL
DECLARE #TableCursor CURSOR
SET #TableCursor = CURSOR FOR
SELECT name FROM #TempTableDatas
OPEN #TableCursor
FETCH NEXT FROM #TableCursor INTO #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #TableName, #DBName
FETCH NEXT FROM #TableCursor INTO #TableName
END
CLOSE #TableCursor
DEALLOCATE #TableCursor
DROP TABLE #TempTableDatas
FETCH NEXT FROM #DBCursor INTO #DBName
END
CLOSE #DBCursor
DEALLOCATE #DBCursor
Say I want to run the following:
update users set age = 10
on databases:
db1, db2, db3
All on the same server, I want to loop through and perform the same action.
Currently I am doing this manually using management studio via the dropdown.
Hoping there is a better way.
You could probably do it with dynamic SQL. Something like so:
create table #dbs (db_name sysname not null)
insert into #dbs values ('db1'),('db2'),('db3')
declare curs cursor for
select db_name from #dbs
declare #db sysname, #sql nvarchar(max)
open curs
while(1=1)
begin
fetch next from curs into #db
if (##fetch_status <> 0)
break
set #sql = 'update ' + quotename(#db) + '.dbo.users set age = 10'
exec(#sql)
end
close curs
deallocate curs
drop table #dbs
Not sure about doing it 'dynamically', i.e. a FOR-EACH style loop on all the databases in a server, but this should work:
USE db1
update users set age = 10
GO
USE db2
update users set age = 10
GO
USE db3
update users set age = 10
Designate a server as a central management server and then add the other servers to the server group. Then you can run the update on all databases within the group. http://msdn.microsoft.com/en-us/library/bb934126.aspx
use [WWAUTHxxx__] -- a db containing active databases.
set nocount on
declare #Catalog as nvarchar(32)
declare #LibraryName as varchar(255)
declare #dbtable as varchar(50)
declare #retval as nvarchar(50)
declare #sSQL as nvarchar(max)
declare #parmdef as nvarchar(500)
declare #retvalout as nvarchar(50)
Declare Library_Cursor Cursor for
select top(1000) xCatalog, xLibraryName
from Active_DBs
order by xcatalog
Open Library_Cursor;
Fetch Next from Library_Cursor into #Catalog, #LibraryName
while ##Fetch_status = 0
begin
set #dbTable = #Catalog + '.dbo.las_circperiods'
set #ParmDef = N'#retvalOUT int OUTPUT';
set #sSQL = N'Select #retvalout = count(*) from ' + #dbtable
+ ' where xlastcircdate is null'
exec sp_executesql #ssql,#parmdef,#retvalout=#retval output
if #retval > 0 -- check/print Sql and then activate.
-- I like checking to see the potentially affected databases.
begin
print #Catalog + ',' + #LibraryName + ',' + #retval
set #ssql = N'update ' + #dbTable
+ ' set xlastcircdate = '''' '
+ ' where xlastcircdate is null'
-- print #ssql -- View what you might will do
exec sp_executesql #ssql -- Do it.
end
Fetch Next from Library_Cursor into #Catalog, #LibraryName
end;
close Library_cursor
Deallocate Library_cursor
set #SQL=N' select #minTableId = MIN(id) from ' + #AcDB + '.dbo.vTblOfRollNo '
Declare Cursor For
EXEC SP_EXECUTESQL #SQL
if i have declared all the variables in above query but Declaration of cursor in above
query shows ERROR.
What is Solution?
In order to execute a cursor over dynamic SQL you must put the output of your dynamic sql into a temporary table and then cursor over the temporary table like this:
DECLARE #TableName NVARCHAR(100)
DECLARE #SQL NVARCHAR(1000)
CREATE TABLE #TempTABLE(email NVARCHAR(200))
SET #TableName='Users'
SELECT #SQL='INSERT INTO #TempTable SELECT email FROM ' + #TableName
EXEC (#SQL)
DECLARE MyCursor CURSOR FOR SELECT * FROM #TempTable
OPEN MyCursor
DECLARE #Email NVARCHAR(200)
FETCH NEXT FROM MyCursor INTO #Email
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT 'Email = ' + #Email
FETCH NEXT FROM MyCursor INTO #Email
END
CLOSE MyCursor
DEALLOCATE MyCursor
DROP TABLE #TempTABLE
I dont think you need a cursor for this
try
DECLARE #AcDB VARCHAR(10),
#Sql NVARCHAR(MAX)
set #SQL=N' select MIN(id) from ' + #AcDB + '.dbo.vTblOfRollNo '
DECLARE #Temp TABLE(
MinID INT
)
INSERT INTO #Temp EXEC SP_EXECUTESQL #SQL
DECLARE #minTableId INT
SELECT TOP 1 #minTableId = MinID FROM #Temp
SELECT #minTableId
EDIT: Also here is the actual CURSOR documentation
DECLARE CURSOR (Transact-SQL)