Why does this work perfectly:
SET #columnQuery = 'INSERT INTO ColumnNames SELECT ORDINAL_POSITION, COLUMN_NAME FROM information_schema.columns WHERE TABLE_NAME=''residents'' ORDER BY ORDINAL_POSITION;';
PREPARE STMT FROM #columnQuery;
EXECUTE STMT;
but this does not:
DECLARE TableName VARCHAR(50);
SET #TableName = 'residents';
SET #columnQuery = 'INSERT INTO ColumnNames SELECT ORDINAL_POSITION, COLUMN_NAME FROM information_schema.columns WHERE TABLE_NAME=''' + #TableName + ''' ORDER BY ORDINAL_POSITION;';
PREPARE STMT FROM #columnQuery;
EXECUTE STMT;
and neither does this:
DECLARE TableName VARCHAR(50);
SET #TableName = 'residents';
SET #columnQuery = CONCAT('INSERT INTO ColumnNames SELECT ORDINAL_POSITION, COLUMN_NAME FROM information_schema.columns WHERE TABLE_NAME=''', #TableName, ''' ORDER BY ORDINAL_POSITION;');
PREPARE STMT FROM #columnQuery;
EXECUTE STMT;
Neither does this:
SET #columnQuery = 'INSERT INTO ColumnNames SELECT ORDINAL_POSITION, COLUMN_NAME FROM information_schema.columns WHERE TABLE_NAME=? ORDER BY ORDINAL_POSITION;';
PREPARE STMT FROM #columnQuery;
EXECUTE STMT USING #TableName;
Here is the part of the sproc that is giving me issues:
CREATE PROCEDURE sp_ReturnSingleRowAsXml
(
IN TableName VARCHAR(50)
)
BEGIN
DECLARE columnQuery VARCHAR(1000);
DROP TABLE IF EXISTS ColumnNames;
CREATE TEMPORARY TABLE ColumnNames (
ID INT, ColumnName VARCHAR(50)
);
SET #columnQuery = 'INSERT INTO ColumnNames SELECT ORDINAL_POSITION, COLUMN_NAME FROM information_schema.columns WHERE TABLE_NAME=''' + #TableName + ''' ORDER BY ORDINAL_POSITION;';
PREPARE STMT FROM #columnQuery;
EXECUTE STMT;
select * from ColumnNames;
END;
CALL sp_ReturnSingleRowAsXml('residents');
The select returns nothing when it should return about 40 rows. BUT, if I hard code the word 'residents' IN the #columnQuery, I get results! And yes, there is definitely a table named 'residents'.
Sometimes I get this error, sometimes I don't, depending on whether I'm using CONCAT or just manually concatenating strings:
MySQL Database Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1
I was able to get it to work with the following:
CREATE PROCEDURE `sp_ReturnSingleRowAsXml`(
IN TableName VARCHAR(50)
)
BEGIN
DROP TABLE IF EXISTS ColumnNames;
CREATE TEMPORARY TABLE ColumnNames (
ID INT, ColumnName VARCHAR(50)
);
SET #tblName = TableName;
SET #columnQuery = 'INSERT INTO ColumnNames SELECT ORDINAL_POSITION, COLUMN_NAME FROM information_schema.columns WHERE TABLE_NAME=? ORDER BY ORDINAL_POSITION;';
PREPARE STMT FROM #columnQuery;
EXECUTE STMT USING #tblName;
select * from ColumnNames;
END
try this:
DECLARE TableName VARCHAR(50);
SET #TableName = 'residents';
SET #columnQuery = 'INSERT INTO ColumnNames SELECT ORDINAL_POSITION, COLUMN_NAME FROM information_schema.columns WHERE TABLE_NAME=? ORDER BY ORDINAL_POSITION;';
PREPARE STMT FROM #columnQuery;
EXECUTE STMT USING #TableName;
Related
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;
I have this SQL query
SELECT table_name
INTO #LukaTestTable
FROM information_schema.columns
WHERE column_name = 'GUID'
ORDER BY TABLE_NAME ;
How get the value of the column GUID in all tables with the name from TABLE_NAME?
Or can I get table like?
TABLE_NAME GUID_VALUE
In order to be able to query a table before you know what table you want you have to use dynamic queries. If you have an arbitrary number of tables, in SQL Server you could achieve this with cursors:
DECLARE
#column VARCHAR(256) = 'GUID',
#table VARCHAR(256),
#query VARCHAR(4000);
DECLARE #Tables CURSOR LOCAL FAST_FORWARD
FOR
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = #column
ORDER BY TABLE_NAME;
OPEN #Tables
FETCH NEXT FROM #Tables INTO #table
WHILE ##FETCH_STATUS = 0
BEGIN
SET #query = 'SELECT ' + #column + ' FROM ' + #table
EXEC(#query)
FETCH NEXT FROM #Tables INTO #table
END
CLOSE #Tables
DEALLOCATE #Tables;
If you're sure your 'GUID' column will have same data type - you can create a temp table and insert to it in WHILE loop and SELECT everything in one go at the end.
You can use dynamic sql like this:
declare #sql varchar(max) = cast (' ' as varchar(max));
select #sql = #sql +
(select ' select GUID from ' + quotename(table_name) + ' union all ' as 'text()'
from #LukaTestTable
for xml path(''));
set #sql = reverse(stuff(reverse(#sql), 1, 10, ''));
--print #sql
exec(#sql);
And if you want table_name as e separate column you should first save it in your #LukaTestTable
Try this below script using While loop and dynamic Sql
IF OBJECT_ID('tempdb..#GetSqlQuery') IS NOT NULL
DROP TABLE #GetSqlQuery
IF OBJECT_ID('tempdb..#GetSpecficcolumnvalue') IS NOT NULL
DROP TABLE #GetSpecficcolumnvalue
GO
CREATE TABLE #GetSqlQuery
(
ID INT IDENTITY
,SELECtQuery nvarchar(max)
,TableName varchar(200)
)
CREATE TABLE #GetSpecficcolumnvalue
(
ID INT IDENTITY
,GetValue nvarchar(max)
,TableName varchar(200)
)
INSERT INTO #GetSqlQuery(SELECtQuery,TableName)
SELECT 'SELECT GUID,'''+TABLE_NAME+''' As TableName FROM '+QUOTENAME(TABLE_NAME) AS SELECtQuery,QUOTENAME(TABLE_NAME) AS TableName
FROM(
SELECT
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME ='GUID'
)dt
ORDER BY TABLE_NAME
DEclare #MinId INt,#MaxId INT,#Sql nvarchar(maX),#TableName varchar(1000)
SELECT #MinId =MIN(Id),#MaxId=MAX(ID) FROM #GetSqlQuery
WHILE (#MinId<=#MaxId)
BEgin
SELECT #Sql=SELECtQuery ,#TableName=TableName From #GetSqlQuery WHERE ID=#MinId
PRINT #Sql
INSERT INTO #GetSpecficcolumnvalue(GetValue,TableName)
EXEC (#Sql)
SET #MinId=#MinId+1
END
SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 1)) AS Seq,GetValue,TableName
FROM
(
SELECT *, ROW_NUMBER ()OVER(PArtition by GetValue,TableName ORDER BY
TableName) AS dup FROM #GetSpecficcolumnvalue
)dt where dt.dup=1
I have a query, that returns multiple tables, something like that:
SELECT TableName, DatabaseName +'.'+ TableName, ColumnName
FROM DBC.Columns
WHERE ColumnName = 'id'
And I need to loop through these tables by looking to the information stored in these tables, in order to get only specific tables.
I tried something like code below, using 'LOOP' and cursor, but it says that Query is invalid (code have been taken from here):
DECLARE cursor_Tables CURSOR FOR
SELECT DatabaseName || '.' || TableName
FROM DBC.Columns
WHERE ColumnName ='id';
OPEN cursor_Tables;
label1:
LOOP
FETCH cursor_Tables into tbName;
IF (SQLSTATE ='02000') THEN
LEAVE label1;
END IF;
CASE WHEN (
SELECT COUNT(*)
FROM prd3_db_tmd.K_PTY_NK01
WHERE id = 0 ) > 0
THEN tbName
END
END LOOP label1;
CLOSE cursor_Tables;
END;
How can I actually deal with this problem? Do I need to use procedure in addition? DBMS is Teradata
You need a Stored Procedure because this is the only place where you can use a cursor in Teradata.
REPLACE PROCEDURE testproc()
DYNAMIC RESULT SETS 1
BEGIN
DECLARE tbName VARCHAR(257);
DECLARE SqlStr VARCHAR(500);
-- temporary table to store the result set
CREATE VOLATILE TABLE _vt_(tbName VARCHAR(257)) ON COMMIT PRESERVE ROWS;
-- your existing query to return the table name
-- Better use ColumnsV instead of Columns
FOR cursor_Tables AS
SELECT DatabaseName || '.' || TABLENAME AS tbName
FROM DBC.ColumnsV
WHERE ColumnName ='id'
DO -- prepare the dynamic SQL ...
SET SqlStr =
'insert into _vt_
select ''' || cursor_tables.tbName || '''
from ' || cursor_tables.tbName || '
where id = 0
having count(*) > 0;
';
-- ... and run it
EXECUTE IMMEDIATE SqlStr;
END FOR;
BEGIN -- return the result set
DECLARE resultset CURSOR WITH RETURN ONLY FOR S1;
SET SqlStr = 'SELECT * FROM _vt_;';
PREPARE S1 FROM SqlStr;
OPEN resultset;
END;
DROP TABLE vt;
END;
If this is SQL Server you can check following SQL cursor, I edited the cursor declaration and the code within
Although they may differ from your requirement, I think you can modify easily
declare #sql nvarchar(max)
declare #tablename nvarchar(100)
DECLARE cursor_Tables CURSOR FOR
SELECT s.name + '.' + o.name
--s.name [schema], o.name [table]
FROM sys.Columns c
inner join sys.objects o on c.object_id = o.object_id
inner join sys.schemas s on s.schema_id = o.schema_id
WHERE c.Name ='id' and o.type = 'U'
/*
SELECT TableName, DatabaseName +'.'+ TableName, ColumnName
FROM DBC.Columns
WHERE ColumnName = 'id'
*/
OPEN cursor_Tables;
FETCH NEXT FROM cursor_Tables INTO #tablename
WHILE ##FETCH_STATUS = 0
BEGIN
-- print #tablename
set #sql = 'select case when count(*) > 0 then ''' + #tablename + ''' else '''' end from ' + #tablename
exec sp_executesql #sql
FETCH NEXT FROM cursor_Tables INTO #tablename
END
CLOSE cursor_Tables;
DEALLOCATE cursor_Tables;
On SQL Server, sp_MsForEachTable undocumented stored procedure can be used instead of a loop structure like a cursor
Please check the below SQL command
EXEC sp_MSForEachTable 'IF EXISTS(select * from sys.columns where name = ''Id'' and object_id = object_id(''?''))SELECT ''?'', COUNT(*) FROM ?'
The syntax may be difficult if you are using the sp_msforeachtable or sp_msforeachdb, but you can find samples on the web
You could create a variable to hold the number of rows and set it equal to the count:
DECLARE #count INT
SELECT #count = COUNT(*)
FROM prd3_db_tmd.K_PTY_NK01
WHERE id = 0
Then use an if statement to select the table if it has rows that meet your criteria:
IF #count > 0
BEGIN
SELECT tbName
END
Also as a side note without having SELECT in front of your CASE statement the syntax is invalid, you may want to try it with just adding SELECT in front of CASE if you don't like the way mentioned above
You need to use dynamic SQL. If you need to see the info on the table, you can create a synonym.
CURSOR cursor_Tables is
SELECT DatabaseName || '.' || TableName AS tbName
FROM DBC.Columns
WHERE ColumnName ='id';
begin
FOR R IN cursor_Tables
LOOP
execute immediate 'CREATE OR REPLACE SYNONYM your_synonym FOR '|| R.tbName ;
select *
from your_synonym;
END LOOP;
END;
Or if you want you can create a view.
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.
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