Running SQL query for common table in all databases - sql

I'm trying to run SQL query to populate result against a common table in all databases.. however it is resulting in false output
Create table #userid (dbname varchar(50), username varchar(50))
EXEC sp_MSforeachdb 'IF ''?'' NOT IN (''master'',''security'',''tempdb'')
BEGIN
inset into #userid
select ''?'' dbname, username from zuserdb where username IN (''a1234'',''b1234'')
END'
Select * from #userid
DROP table #userid
Above Code isn't generating right output .. multiple rows are being generated however user actually doesn't exist in database. Any suggestions

Not sure why that is happening it is undocumented, but here is one workaround.
Use three part identifier in table name. Considering zuserdb is present in dbo schema in all the database.
CREATE TABLE #userid
(
dbname VARCHAR(50),
username VARCHAR(50)
)
EXEC Sp_msforeachdb
'IF ''?'' NOT IN (''master'',''security'',''tempdb'',''model'',''msdb'')
BEGIN
insert into #userid
select ''?'' dbname, username from ?.dbo.zuserdb where username IN (''a1234'',''b1234'')
END'
SELECT *
FROM #userid
DROP TABLE #userid
Added model & msdb databases also in exclude list because those are also system databases

Related

How to find, across multiple databases, a specific table (common to most/all) that is not empty

I am working in an environment where many users have the same (or almost identical) test database set up on a common MSSQL server. We are talking about well over 100 databases for testing purposes. And at the very least, 95+% of them will contain the table I am trying to target.
These test databases are only filled with junk data - I will not be impacting anyone by doing any kind of a search. I am looking at one table, specifically, and I need to determine if any test database has that table actually containing any data at all. It doesn’t matter what the data is, I just need to find a table actually containing any data, so I can determine why that data exists in the first place. (This DB is quite old - almost two decades, so sometimes no-one has a clear answer why something in it exists).
I have been trying to build an SQL statement that iterates through all the databases, and checks that particular table specifically to see if it has any content, to bring back a list of databases that have that table containing data.
So to be specific: I need to find all databases where a specific table has any content at all (COUNT(*) > 0). Right now totally stuck with not much of any clues as to how to proceed.
In both methods replace <tablename> with the table name
Using sp_foreachdb
You can use sp_foreachDb
CREATE TABLE ##TBLTEMP(dbname varchar(100), rowscount int)
DECLARE #command varchar(4000)
SELECT #command =
'if exists(select 1 from [?].INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME =''<TABLE NAME>'') insert into ##TBLTEMP(dbname,rowscount) select ''[?]'',count(*) from [?].dbo.<tablename>'
EXEC sp_MSforeachdb #command
SELECT * FROM ##TBLTEMP WHERE rowscount > 0
DROP TABLE ##TBLTEMP
Using CURSOR
CREATE TABLE ##TBLTEMP(dbname varchar(100), rowscount int)
DECLARE #dbname Varchar(100), #strQuery varchar(4000)
DECLARE csr CURSOR FOR SELECT [name] FROM sys.databases
FETCH NEXT FROM csr INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #strQuery = 'if exists(select 1 from [' + #dbname +'].INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME =''<TABLE NAME>'') INSERT INTO ##TBLTEMP(dbname,rowscount) SELECT ''' + #dbname + '' ', COUNT(*) FROM [' + #dbname + '].[dbo].<table name>'
EXEC(#strQuery)
FETCH NEXT FROM csr INTO #dbname
END
CLOSE csr
DEALLOCATE csr
SELECT * FROM ##TBLTEMP where rowscount > 0
References
Sp MSforeachDB
Run same command on all SQL Server databases without cursors
DECLARE CURSOR (Transact-SQL)

SQL column value to table name

In my SQL database, I would like to make a general purpose soft link table. Perhaps something similar the following:
create table soft_link(
id uniqueidentifier,
name varchar(255),
LINK uniqueidentifier,
TABLE varchar(255),
primary key(id));
Say I have object "b_object" in some other table in the database. The LINK column would be the the unique identifier of b_object, and TABLE would be the table in which b_object is stored within the database.
Now I want to make a single stored procedure "sp_ResolveSoftLink". This method will take an id of a soft link, look up the LINK and TABLE columns of the soft link, and then use the TABLE and LINK to query for b_object.
The following is NOT proper SQL syntax, but hopefully it helps illustrate my question. I want to combine these two queries into a single stored procedure and return the result of the second query:
select LINK, TABLE from soft_link where id = xxxxxx
select * from TABLE where id = LINK
-- return the result of the second select query
FUNDAMENTAL QUESTION: How/can I use the varchar return from one query to form another query in the same stored procedure in SQL?
You can create a Stored procedure like this.
Here, First you have to store value of LINK and Table in variable and then use these variable to form another Dynamic Query
CREATE PROC spName
#id INT
AS
BEGIN
Declare #LINKValue uniqueidentifier, #TABLE varchar(255),#SQL varchar(max)
SELECT #LINKValue = LINK , #TABLE = TABLE
FROM soft_link
WHERE soft_link id = #id
SET #SQL='SELECT * FROM';
SET #SQL = #SQL +' ' + #TABLE
SET #SQL = #SQL +' ' + 'WHERE ID =' +' ' + #LINKValue
PRINT #SQL -- SEE Here This is what you actually Want
--EXEC (#SQL) --Then Execute this
END

Search databases for table with values

I am using SQL Server 2008. My question is, is it possible, given a table name, to construct a query that returns a list of databases that contain that table WITH values (meaning it is not empty)?
For example, I have a table called tbl_Name. I have 100 databases, and in 90 of them tbl_Name is empty. Can I get a list of the 10 databases where tbl_Name has values?
You can do this with a cursor, and the stored procedure sp_msforeachdb.
sp_msforeachdb is, as the name suggests, a proc that runs something for each database. You can use this to list all db's with a given table name:
sp_msforeachdb 'SELECT "?" AS db from [?].sys.tables WHERE name = ''tbl_Name'''
Inserting those records into a temp table makes it easy to iterate over in a cursor:
DROP TABLE #db_List
DROP TABLE #Not_Empty
GO
CREATE TABLE #db_List (db VARCHAR(MAX))
CREATE TABLE #Not_Empty (db VARCHAR(MAX))
GO
sp_msforeachdb 'INSERT INTO #db_List SELECT "?" AS db from [?].sys.tables WHERE name = ''tbl_Name'''
GO
SET NOCOUNT ON
DECLARE #Iterator varchar(MAX)
,#strSQL varchar(MAX)
DECLARE xyz CURSOR
FOR
--Select stuff to iterate over
SELECT *
FROM #db_List
OPEN xyz
FETCH NEXT FROM xyz
INTO #Iterator
WHILE ##FETCH_STATUS = 0
BEGIN
--Do stuff
SET #strSQL = 'INSERT INTO #Not_Empty
SELECT '''+#Iterator+'''
WHERE EXISTS (SELECT TOP 1 * FROM '+#Iterator+'..tbl_Name)
'
Exec (#strSQL)
FETCH NEXT FROM xyz
INTO #Iterator
END
CLOSE xyz
DEALLOCATE xyz
GO
SET NOCOUNT OFF
Quick summary:
Start in master DB select from sys.databases, get all the DB's, cursor thru each one (USE the DB). Use EXEC( sqlStatement ) to perform your command etc...
Now that you're in the DB (Each DB has a table named sys.objects, so your goal from the above paragraph is to simply issue a command like EXEC(USE dbName) ) list through the list of tables, select from sys.objects, look for object types of 'U' (user table). Get the name, construct your SELECT * FROM INTO #yourTemp WHERE blah blah blah insert your results in a #temp table you created at the very beginning.. Issue the SQL via EXEC()

Put the servername, database name and schema automatically before the tablename in a select statement

I have a stored procedure that is responsible to import data from database A to database B. I have customers, they all have their own database B (with the same tables etc.) They also have their own database A. The stored procedure will be executed (deployed) on database B.
The problem:
Each customer have another database name for A and B. I found also that database A can be on a different server/instance. I need a generic way to put automatically the server/instance name and the database name from A in my stored procedure to select data from there. Every customer has a connectstring to database A which is already exists in database B. So from the connecstring, I can get the server/instance name and the databasename of A. (I already created a linked server)
1. What is the best way to put the server/instance name and the database name before the table name??
Stored procedure
In my stored procedure I have used a lot of variable (declare) tables to insert the data from database A. There are many articles about using dynamic sql but, I cant find an example with a declare table.
My solution
I am thinking about inserting all the data from database A to variable tables. I am importing data from 7 tables, so I need to declare 7 tables and further in my SP I can select data from my declare tables. Note that the hole stored procedure is very huge.
Questions
2.What do you think about my solution?
3.Do you have another solution?
4.How can I insert into my declare table using dynamic sql?
**note that I am using sql server 2005.
I have a few statements like below:
declare #Temp table (Id int, etc
insert into #Temp (Id, etc)
Select Id, etc
From [databasename].dbo.TableName //hardcoded
Where .......
// doing staff like selecting from the #Temp table etc.
I also have subqueries, but I can change if it is necessary.
You can't use dynamic sql to enter into declare tables as the temporary table is only available in the session. Executing any new sql i.e. through dynamic sql will create a new session.
You can get around it by not using any declared or temp tables but instead using a normal table. The dynamic sql will have access to this and anything you do to it isnt lost.
You can prefix your normal tables with something like Temp_ just to note they are temp tables and then make sure you drop them at the beginning of each query i.e.
DROP TABLE TEMP_Table
You can call multiple local databases by doing
SELECT * FROM [DatabaseName].dbo.[TableName]
Instead of creating #temp, create it as [TempDB].[DBO].[Temp] and it will be accessible outside the dynamic SQL. However, remember to explicitly drop the table, once you are done
DECLARE #sql VARCHAR(200)
SET #sql = 'CREATE TABLE tempdb.dbo.temp(id INT IDENTITY(1,1), DESCRIPTION VARCHAR(100))
INSERT INTO tempdb.dbo.temp SELECT ''1'' SELECT * FROM tempdb.dbo.temp'
PRINT (#sql)
EXEC (#sql)
SELECT * FROM tempdb.dbo.temp
DROP TABLE tempdb.dbo.temp
Raj
Check this for creating temporary table in dynamic query
DECLARE #sql VARCHAR(200)
SET #sql = 'CREATE TABLE #temp(id INT IDENTITY(1,1), DESCRIPTION VARCHAR(100))
INSERT INTO #temp SELECT ''1'' SELECT * FROM #temp'
PRINT (#sql)
EXEC (#sql)
SQLFiddle
to be precise
DECLARE #sql VARCHAR(1000)
SET #sql =
'DECLARE #Temp TABLE (
Id INT,
etc
INSERT INTO #Temp (Id, etc)
SELECT Id,
etc
FROM [databasename].dbo.TableName / / hardcoded
WHERE ....... SELECT * FROM #temp'
PRINT (#sql)
EXEC (#sql)

How to rename users, add a role etc, using script in t-sql

I have to
Rename users (from yyyyyy\xxxx to xxxx)
Add a role to the users
See the priviliges of stored procedures granted to a specified role (I found a table with the information regarding tables, but not stored procedure)
All in t-sql. I know how to do it mannualy, but with 400+ users, I hope to script me out of the problems.
Can anyone help?
What you need to do is loop over the users to modify and execute the commands to make the changes you need. You can do this by querying the syslogins table and creating a cursor with the results.
I have added the statement to rename the user, but adding the role is as simple as adding in a second statement and exec with sp_addrolemember
DECLARE #Login as varchar(50);
DECLARE LoginsCrsr CURSOR FOR
SELECT name
FROM syslogins
WHERE name like '%John%'; --Whatever critera you need
OPEN LoginsCrsr;
FETCH NEXT FROM LoginsCrsr
INTO #Login;
WHILE (##FETCH_STATUS = 0)
BEGIN
DECLARE #TSQL as varchar(255)
DECLARE #NewLogin as varchar(50)
SELECT #NewLogin = #Login -- Do your own thing here
SELECT #TSQL = 'ALTER LOGIN [' + #Login + '] WITH NAME=[' + #NewLogin + ']'
PRINT #TSQL
EXEC (#TSQL)
--Whatever else you need to do
FETCH NEXT FROM LoginsCrsr
INTO #Login
END
GO
CLOSE LoginsCrsr;
DEALLOCATE LoginsCrsr;
GO