I'm trying to loop through my tables and if a column name exists then delete all records within that table.
Here is what I have so far:
select *
from information_schema.columns
order by table_name, ordinal_position
IF EXISTS(
select 'CorporationId'
from information_schema.columns
where TABLE_NAME = #tn
)
BEGIN
PRINT 'Stored procedure already exists';
declare #sql nvarchar(max) = concat('DELETE FROM ', #tn, ' WHERE CorporationId = #CorporationId');
print #sql;
exec sp_executesql #sql, N'#CorporationId uniqueidentifier', #CorporationId=#CorporationId;
END;
At this point, I'm just getting a bunch of CorporationId and I'm not returning that it exists. How do I determine if the column exists and run code if it does?
You ca use below code:
IF EXISTS(
select *
from information_schema.columns
where TABLE_NAME = #tn AND COLUMN_NAME = N'CorporationId'
)
BEGIN
PRINT 'Stored procedure already exists';
declare #sql nvarchar(max) = concat('DELETE FROM ', #tn, ' WHERE CorporationId = #CorporationId');
print #sql;
exec sp_executesql #sql, N'#CorporationId uniqueidentifier', #CorporationId=#CorporationId;
END;
Related
I have code like this:
IF (#schema NOT IN (SELECT TABLE_SCHEMA
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_CATALOG = 'Testowa'
))
BEGIN
declare #sql nvarchar(MAX) = 'create schema ' +#schema+ ''
EXEC sp_executesql #sql
EXEC(#Sql1)
EXEC(#Sql2)
EXEC(#Sql3)
EXEC(#Sql4)
EXEC(#Sql5)
EXEC(#Sql6)
EXEC(#Sql7)
EXEC(#Sql8)
END
ELSE
It makes everything in one moment, I want to make some breaks after #sql and after #sql6
I tried with 'GO', but 'GO' stops IF. 'Breaks' = First do #sql After that Make #sql1-6 After that #Sql7-8. How should I make it?
This looks ugly but would do what you want:
SELECT CASE WHEN #schema NOT IN
(
SELECT TABLE_SCHEMA
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_CATALOG='Testowa'
)
THEN 1
ELSE 0
END AS schemaExists
INTO #tmp;
IF EXISTS (SELECT * FROM #tmp WHERE schemaExists=0)
BEGIN
DECLARE #sql NVARCHAR(MAX) =N'create schema '+#schema+N'';
EXEC sp_executesql #sql;
END;
GO
IF EXISTS (SELECT * FROM #tmp WHERE schemaExists=0)
BEGIN
EXEC(#Sql1);
EXEC(#Sql2);
EXEC(#Sql3);
EXEC(#Sql4);
EXEC(#Sql5);
EXEC(#Sql6);
END;
GO
IF EXISTS (SELECT * FROM #tmp WHERE schemaExists=0)
BEGIN
EXEC(#Sql7);
EXEC(#Sql8);
END;
GO
IF NOT EXISTS (SELECT * FROM #tmp WHERE schemaExists=0) -- ELSE
BEGIN
--
PRINT 'Blah Blah';
END;
GO
DROP TABLE #tmp;
It could be rewritten as:
IF NOT EXISTS (SELECT 1
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE CATALOG_NAME = 'Testowa'
AND SCHEMA_NAME = #schema)
BEGIN
DECLARE #sql NVARCHAR(MAX) = 'CREATE SCHEMA ' + QUOTENAME(#schema);
PRINT #sql;
EXEC(#sql);
WAITFOR DELAY '00:05'; -- "break"
EXEC(...);
EXEC(...);
WAITFOR DELAY '00:05';
EXEC(...);
END;
Notes:
; are recommended
variable provided into dynamic SQL should be parametrized sp_executesql, if they are concatenated identifiers QUOTENAME should be used
WAITFOR as "break"
to find if schema exists INFROMATION_SCHEMA.SCHEMATA could be used instead of TABLES
PRINT as debug
I'm running the below stored procedure sp_MSforeachdb with a simple command. My question is how to limit the result to show only the databases that have at least 1 record satisfying the command:
Here's my stored procedure:
EXECUTE master.sys.sp_MSforeachdb 'USE [?];
IF (EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = ''Tabs''))
BEGIN
SELECT ''?'' as dbname,T.TabName, T.TabPath
FROM Tabs T
WHERE T.TabID IN (
SELECT Distinct TM.TabID
FROM TabModules TM
WHERE mID IN (
...
)
)
ORDER BY T.TabName
END
'
Any ideas how I can modify the sp so that it doesn't display the databases that have empty results (see image)?
Well, first, stop using sp_MSforEachDb. Oh, the problems (if you want proof, see here).
How about:
DECLARE #cmd NVARCHAR(MAX) = N'', #sql NVARCHAR(MAX) = N'';
SELECT #cmd += N'IF EXISTS (SELECT 1 FROM '
+ QUOTENAME(name) + '.sys.tables WHERE name = N''Tabs'')
SET #sql += N''UNION ALL
SELECT ''''' + name + ''''',T.TabName
FROM ' + QUOTENAME(name) + '.dbo.Tabs AS T
WHERE EXISTS
(
SELECT 1 FROM ' + QUOTENAME(name) + '.dbo.TabModules AS TM
WHERE TM.TabID = T.TabID
AND TM.mID IN -- this should probably be exists too
(
...
)
)
'''
FROM sys.databases
WHERE state = 0 -- assume you only want online databases
AND database_id > 4; -- assume you don't want system dbs
EXEC sp_executesql #cmd, N'#sql NVARCHAR(MAX) OUTPUT', #sql OUTPUT;
SET #sql = STUFF(#sql, 1, 10, '') + N' ORDER BY TabName;';
PRINT #sql; -- this will appear truncated, but trust me, it is not truncated
-- EXEC sp_executesql #sql;
If you really want some unknown, arbitrary number of separate resultsets, the change is simple.
DECLARE #cmd NVARCHAR(MAX) = N'', #sql NVARCHAR(MAX) = N'';
SELECT #cmd += N'IF EXISTS (SELECT 1 FROM '
+ QUOTENAME(name) + '.sys.tables WHERE name = N''Tabs'')
SET #sql += N''SELECT ''''' + name + ''''',T.TabName
FROM ' + QUOTENAME(name) + '.dbo.Tabs AS T
WHERE EXISTS
(
SELECT 1 FROM ' + QUOTENAME(name) + '.dbo.TabModules AS TM
WHERE TM.TabID = T.TabID
AND TM.mID IN -- this should probably be exists too
(
...
)
)
ORDER BY T.TabName;
'';'
FROM sys.databases
WHERE state = 0 -- assume you only want online databases
--AND database_id > 4; -- assume you don't want system dbs
EXEC sp_executesql #cmd, N'#sql NVARCHAR(MAX) OUTPUT', #sql OUTPUT;
PRINT #sql; -- this will appear truncated, but trust me, it is not truncated
-- EXEC sp_executesql #sql;
You basically need another IF to only run the select if data exists.
Here's what i did to test.
On DB1:
create table mytesttable(a int)
insert mytesttable values(1)
On DB2:
create table mytesttable(a int)
So you want DB1 to return results, but DB2 not to. you can use the following sql:
EXECUTE master.sys.sp_MSforeachdb 'USE [?];
IF (EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = ''mytesttable''))
BEGIN
IF EXISTS (SELECT 1 FROM mytesttable) BEGIN
SELECT ''?'' as dbname,T.A
FROM mytesttable AS T
END
END
'
This only returns:
db1, 1
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
how do find the number of rows in a table when the table name is in a variable?
I need to find tables in a SQL Server database (2000) that contain one value for a column.
I can use the following query to output a list of possible candidate tables containing my_column:
SELECT DISTINCT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = 'my_column'
What I would like to get at, is the following pseudo query with result:
select '$TABLE_NAME', count(*) from $TABLE_NAME where my_column = '12345'
table01 1
table02 5
table03 0
table04 3
Or more generally formulated: Is it possible to make the FROM-clause variable?
Only way it's possible is by using dynamic SQL:
declare #stmt nvarchar(max), #value nvarchar(max)
select #stmt = isnull(#stmt + ' union all ', '') + '
select ''' + TABLE_NAME + ''', count(*) from ' + TABLE_NAME + ' where my_column = #value'
from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME = 'my_column'
select #value = '12345'
exec sp_executesql
#stmt = #stmt,
#params = N'#value nvarchar(max)',
#value = #value
update:
For SQL 2000 you can use nvarchar(4000) If you have really big number of tables, you can use temporary table + cursor:
create table #Temp_Results (table_name nvarchar(128), cnt int)
declare #stmt nvarchar(4000), #value nvarchar(128)
declare t_cursor cursor local fast_forward for
select
'select ''' + TABLE_NAME + ''', count(*) from ' + TABLE_NAME + ' where id = #value'
from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME = 'name'
select #value = 1
open t_cursor
fetch t_cursor into #stmt
while ##fetch_status = 0
begin
insert into #Temp_Results
exec sp_executesql
#stmt = #stmt,
#params = N'#value nvarchar(128)',
#value = #value
fetch t_cursor into #stmt
end
close t_cursor
deallocate t_cursor
select * from #Temp_Results
You can use the sp_MSforeachtable undocumented stored procedure to make the FROM clause variable.Here is an article that shows how to use it: sp_msForEachTable examples
If I understand the question, you want a list of tables containing a given column name and a record count from each table, yes? If so
select o.name as "Table Name", i.rowcnt as "Rows"
from sysobjects o
inner join sysindexes i on o.id = i.id
where i.indid in (0,1)
and o.id in
(select distinct id from syscolumns where name = 'My_Column')
order by o.name
Requires that you have ability to query system tables.
create procedure qa_cc
#tablename varchar(500)
AS
BEGIN
-- Create two integer values
DECLARE #tableOneCount varchar(50), #tableTwoCount varchar(50)
-- Get the number of rows from the first table
SELECT #tableOneCount = 'SELECT COUNT(*) FROM' + #tablename;
exec (#tableOneCount);
select #tableOneCount ;
END
exec qa_cc #tablename=table1
You could use sp_executesql, like:
declare #sql nvarchar(max);
set #sql = N'select #cnt = count(*) from ' + #tablename;
declare #cnt int;
exec sp_executesql #sql, N'#cnt int output', #cnt = #cnt output;
select #cnt;
SELECT SUM(pa.rows) RowCnt
FROM sys.tables ta
INNER JOIN sys.partitions pa
ON pa.OBJECT_ID = ta.OBJECT_ID
WHERE ta.is_ms_shipped = 0 AND pa.index_id IN (1,0)
and ta.name=#tablename
GROUP BY ta.name
See http://blog.sqlauthority.com/2010/09/08/sql-server-find-row-count-in-table-find-largest-table-in-database-part-2/
Looks like you were missing a space after the FROM keyword which was reading FROMTABLE rather than FROM Table
DECLARE #TABLE NVARCHAR(100)
SET #TABLE = 'CLIENT' -- YOUR TABLE NAME
EXEC('SELECT COUNT(*) FROM ' + #TABLE)
CREATE PROCEDURE [dbo].[TableRowCount]
#tableName text
AS
EXEC ('SELECT COUNT(*) FROM ' + #tableName)
RETURN ##ROWCOUNT
I hope that helps. Thank you.
Environment: SQL Server 2005/2008,
pubs database
I have inserted into a table variable a set of data as shown below using information_schema tables.
Now I would like to update the flag column based on the result of executing the query in the column dSQL. I was able to update using loops/cursor and then used sp_executeSQL to
update the column and then update flag column later. But is there an alternate set-based way to do this without looping through all individual rows?
use pubs
go
declare #dsql Nvarchar(max)='', #tablename varchar(100), #colname varchar(100)
declare #t table (
TABLE_NAME varchar(100),
COLUMN_NAME varchar(100)
)
insert into #t
select distinct t.TABLE_NAME, c.COLUMN_NAME
from information_Schema.tables t
inner join
information_Schema.columns c
on t.TABLE_CATALOG = c.TABLE_CATALOG
where t.TABLE_SCHEMA = c.TABLE_SCHEMA
and t.TABLE_TYPE = 'BASE TABLE'
and c.DATA_TYPE = 'varchar'
select *, Dsql = 'select ' + COLUMN_NAME + ' from ' + TABLE_NAME + ' WHERE '
+ COLUMN_NAME + ' = ''Menlo Park''', '' as Flag
FROM #t
GO
I had an idea to create a function and call the function for each row to execute individual query statement but calling the function for each record might be a performance hit.
It's a loop or a function as you suggested (which is really a loop anyway).
Not possible, I made a script like it earlier.
declare #searchvalue varchar(100)
set nocount off
set #searchvalue = 'Hello world'
create table #tt (table_name varchar(64), column_name varchar(64), count int)
select * into #t from
(
select 'select ''' + a.table_name + ''' ''table_name'',''' + a.column_name + ''' ''column_name'', count(*) count from [' + a.table_name +'] where [' +a.column_name+']='''+#searchvalue +'''' + ' group by ['+ a.column_name+']' sqlstring
from INFORMATION_SCHEMA.COLUMNS a
join
INFORMATION_SCHEMA.TABLES b
on a.table_name = b.table_name
and b.table_type = 'base table'
where data_type = 'varchar'
) a
--loop cursor
Declare #sqlstring as nvarchar(500)
Declare SqlCursor CURSOR FAST_FORWARD FOR
SELECT sqlstring FROM #t
OPEN SqlCursor
FETCH NEXT FROM SqlCursor
INTO #sqlstring
WHILE ##FETCH_STATUS = 0
BEGIN
insert #tt
exec(#sqlstring)
FETCH NEXT FROM SqlCursor
INTO #sqlstring
END
CLOSE SqlCursor
DEALLOCATE SqlCursor
select * from #tt
drop table #tt
drop table #t
Use what you want
This is an old question, but I'd like to add a different answer all the same.
Try the following script (no cursor, no loop (according to execution plan)): (tested in MS SQL 2012)
-- Setting up test data/code
SELECT N'SELECT * FROM INFORMATION_SCHEMA.COLUMNS AS C' T
INTO #Code
UNION ALL
SELECT N'SELECT * FROM INFORMATION_SCHEMA.TABLES AS T'
-- Variable to hold the selected queries, seperated by CrLf. You can also add a "GO" or ";"
DECLARE #SQL NVARCHAR(MAX) = CHAR(13) + CHAR(10)
-- Concatenate the selected queries together into the variable
SELECT #SQL = #SQL + CHAR(13) + CHAR(10) + C.T
FROM #Code AS C
-- Execute
EXEC sys.sp_executesql #SQL
-- Clean up
DROP TABLE #Code