I'm duplicating a series of tables using a loop in SQL. I've inferred from SQL Server Maximum rows that can be inserted in a single insert statment that the maximum rows which can be inserted using a select * is 10,000 for my SQL SERVER. However, the source tables are bigger than 10,000 rows. Is there a way to bypass this limitation without explicitly stating the columns in the select statement, since these will be different for each table?
DECLARE #iTable TABLE (TableName VARCHAR(50),Id int identity(1,1))
INSERT INTO #iTable
Select distinct table_name From INFORMATION_SCHEMA.COLUMNS
Where table_name like 'D0%' OR table_name like 'D1%'
DECLARE #imax int
DECLARE #iSQL VARCHAR(MAX)
DECLARE #iTableName VARCHAR(max)
DECLARE #iid int = 1
select #imax = MAX(Id) from #iTable
WHILE (#iid <= #imax)
BEGIN
SELECT #iTableName = TableName FROM #iTable WHERE Id = #iid
SET #iSQL = 'select * into st_'+ #iTableName +' from '+ #iTableName +';'
EXEC(#iSQL)
SET #iid = #iid +1
END
As already mentioned there is no limitation of the number of rows when using select into. However, you could certainly simplify your code and get rid of that loop.
DECLARE #iSQL NVARCHAR(MAX) = ''
SELECT #iSQL = #iSQL + 'select * into st_'+ TABLE_NAME +' from '+ TABLE_NAME +';'
from INFORMATION_SCHEMA.COLUMNS
Where TABLE_NAME like 'D0%'
OR TABLE_NAME like 'D1%'
group by TABLE_NAME
select #iSQL
--uncomment below when you are satisfied the dynamic sql is correct.
--exec sp_executesql #iSQL
Related
I did this. But unfortunately that return all in many table. I want to return all in one unique table. Maybe using "UNION" but I don't know the way to do.
This is my code:
EXEC sp_msforeachdb 'select ''?''AS "DataBase", s.name, t.name AS "Tables",max(si.rows) as "Rows Line"
from [?].sys.tables t inner join [?].sys.schemas s
on t.schema_id = s.schema_id
inner join [?].sys.partitions si on t.object_id = si.object_id
where t.name like "%ATTACH" group by s.name,t.name'`
You cannot do it in a single query.
You could query the sys.databases table to get a temporary table of all your databases, and then run a dynamic query on each database to store the results of the query in your question all in another temporary table.
Then at the end, you just select all rows from the last temporary table.
I have found finally a solution.i just used a Stored Procedures for having the result i was looking for.So decided to post the answer here maybe that will help someone else.
DECLARE #banco_nome nvarchar(MAX), #tabela_nome nvarchar(MAX)
DECLARE #banco_cursor CURSOR
DECLARE #sqlstatement nvarchar(MAX)
DECLARE #count_sql nvarchar(MAX)
DECLARE #total int
DECLARE #RegistrosFotograficos TABLE
(
DatabaseName nvarchar(max),
TableName nvarchar(max),
Total int
)
SET #banco_cursor = CURSOR FORWARD_ONLY FOR
SELECT name FROM sys.databases
OPEN #banco_cursor
FETCH NEXT FROM #banco_cursor INTO #banco_nome
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sqlstatement = 'DECLARE tabela_cursor CURSOR FORWARD_ONLY FOR SELECT TABLE_NAME FROM ' + #banco_nome + '.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = ''BASE TABLE'' AND TABLE_NAME LIKE ''%ATTACH'' ORDER BY TABLE_NAME'
EXEC sp_executesql #sqlstatement
OPEN tabela_cursor
FETCH NEXT FROM tabela_cursor INTO #tabela_nome
WHILE ##FETCH_STATUS = 0
BEGIN
SET #count_sql = 'USE ' + #banco_nome + '; SELECT #total=COUNT(1) FROM ' + #tabela_nome;
EXECUTE sp_executesql #count_sql, N'#total int OUTPUT', #total=#total OUTPUT
INSERT INTO #RegistrosFotograficos (DatabaseName, TableName, Total) VALUES (#banco_nome, #tabela_nome, #total);
FETCH NEXT FROM tabela_cursor INTO #tabela_nome
END
CLOSE tabela_cursor;
DEALLOCATE tabela_cursor;
FETCH NEXT FROM #banco_cursor INTO #banco_nome
END
CLOSE #banco_cursor;
DEALLOCATE #banco_cursor;
SELECT * FROM #RegistrosFotograficos
This will list all the tables in a given database and the number of rows in each. Notice the results are in a table named #results:
set nocount on
declare #curtable sysname
declare #prevtable sysname
declare #curcount int
declare #tsql varchar(500)
if object_ID('tempdb..#curtables','U') is not null
drop table #curtables
select name into #curtables
from sys.objects
where type='U'
order by 1
if object_id('tempdb..#results','U') is not null
drop table #results
create table #results(name sysname,numrows int)
select top 1 #curtable=name from #curtables order by name
while (1=1)
begin
set #tsql = 'select '''+quotename(#curtable) +''',count(*) numrows from '+quotename(#curtable)
print #tsql
insert into #results
exec (#tsql)
set #prevtable= #curtable
select top 1 #curtable = name
from #curtables
where name > #prevtable
order by name
if #curtable=#prevtable
break
end
I have few tables in my database and I want to count total rows of all those tables based on AppoitmentID for which I use a scalar cursor and a table variable to store some data of those tables based on AppoitmentID. After the end of cursor I count rows of table variable in which I had inserted data using dynamic query in cursor.
But it gives me the following error
Must declare the table variable "#ProcCount".
Is there any other way to get the count of all rows from necessary tables.
Below is my Code :
Create FUNCTION [dbo].[ufn_GetProcedureCount]
(
)
RETURNS INT
AS
BEGIN
-- Declare the return variable here
DECLARE #MenuID bigINT, #TableName VARCHAR(150);
DECLARE #Result int
DECLARE #ProcCount TABLE (AppID INT, WoundId bigINT,TableName varchar(150));
DECLARE #sql nvarchar(2000)
DECLARE #Count int
DECLARE Cur_PendSign Cursor For
select Distinct MenuID,TableName from AppointmentTypeRequiredDocumnet A inner join Menu M on M.ID =A.MenuID where m.MenuGroupID = 8
OPEN Cur_PendSign
FETCH Cur_PendSign INTO #MenuID, #TableName
WHILE ##FETCH_STATUS=0
BEGIN
SET #sql='DECLARE #ProcCount TABLE (AppID INT, WoundId bigINT,TableName varchar(150))'
SET #sql=#sql+'INSERT INTO #ProcCount (AppID,WoundId)
SELECT TOP 1 V.AppointmentID, 1
FROM ['+#TableName+'] V WITH(NOLOCK)'
set #sql=#sql+ 'select count(*) from #ProcCount;'
--set #sql=#sql+ 'DECLARE #Count int'
EXECUTE sp_executesql #sql
FETCH Cur_PendSign INTO #MenuID, #TableName
END
CLOSE Cur_PendSign
DEALLOCATE Cur_PendSign
--set #Result = select count(*) from #ProcCount
RETURN #Result
END
There are two issues with the script.
First: Missing where clause
select Distinct MenuID,TableName from Appointment A.AppointmentID = 8
Second: you need to create persistent table rather than variable table due to limitation of scope as you cant declare variable table outside of EXEC and use it.
This query should work for you. You need to use sp_executesql to execute dynamic queries.
CREATE FUNCTION [dbo].[ufn_GetProcedureCount]
(
)
RETURNS INT
AS
BEGIN
-- Declare the return variable here
DECLARE #Result INT
DECLARE #ProcCount TABLE (
AppID INT,
WoundId BIGINT,
TableName VARCHAR(150)
)
DECLARE #MenuID BIGINT,
#TableName VARCHAR(150)
--Get all table which I need to count rows
DECLARE Cur_PendSign CURSOR FOR
SELECT DISTINCT MenuID, TableName FROM Appointment WHERE AppointmentID = 8
OPEN Cur_PendSign
FETCH Cur_PendSign INTO #MenuID, #TableName
WHILE ##fetch_status = 0
BEGIN
-- Insert require data into #ProcCount using dynamic query
DECLARE #query VARCHAR(255) = 'INSERT INTO #ProcCount (AppID,WoundId,TableName)
SELECT TOP 1 AppointmentID, WoundId, TableName
FROM [' + #TableName + '] WITH(NOLOCK) '
EXECUTE sys.sp_executesql #query
FETCH Cur_PendSign INTO #MenuID, #TableName
END
CLOSE Cur_PendSign
DEALLOCATE Cur_PendSign
--Get Count of all rows from tables
SELECT #Result = COUNT(*) FROM #ProcCount
RETURN #Result
END
Without having a cursor, Loops you can do it with Dynamic coding..
Schema:
(It may be differ with your actual schema)
CREATE TABLE #Appointment (MENUID INT IDENTITY,AppointmentID INT, TableName VARCHAR(20))
INSERT INTO #Appointment
SELECT 1,'TABLE1'
UNION ALL
SELECT 2, 'TABLE2'
UNION ALL
SELECT 8,'TABLE3'
UNION ALL
SELECT 8,'TABLE4'
UNION ALL
SELECT 8,'TABLE5'
Now do like below
DECLARE #QRY VARCHAR(MAX)='';
SELECT #QRY = #QRY+ 'SELECT COUNT(1) AS COUNT_TABLES FROM '+ TableName + ' (NOLOCK)
UNION ALL
' FROM (
SELECT DISTINCT TableName FROM #Appointment A WHERE A.AppointmentID = 8
)A
SELECT #QRY = SUBSTRING(#QRY,1,LEN(#QRY)-11)
SELECT #QRY = '
SELECT SUM(COUNT_TABLES) FROM (
' + #QRY+'
)A'
--PRINT #QRY
EXEC (#QRY)
If you want to check what #QRY contains
/*
SELECT SUM(COUNT_TABLES) FROM (
SELECT COUNT(1) AS COUNT_TABLES FROM TABLE3 (NOLOCK)
UNION ALL
SELECT COUNT(1) AS COUNT_TABLES FROM TABLE4 (NOLOCK)
UNION ALL
SELECT COUNT(1) AS COUNT_TABLES FROM TABLE5 (NOLOCK)
)A
*/
I have several tables with common table names. I want to select all data from them without specifying all tables and union them. I'm thinking of using information_schema.tables to accomplish this.
Tables:
tbl_20160201
tbl_20160202
tbl_20160203
tbl_20160204
tbl_20160205
Query:
SELECT *
FROM (
SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'tbl_201602%'
) a
However, this query only returns the table names and not the data in the tables. I need to union all the tables included in the query. Thank you.
Assuming these tables have the same number of columns and data types, you can use dynamic sql:
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql = #sql +
'SELECT * FROM ' + TABLE_NAME + ' UNION ALL' + CHAR(10)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'tbl_201602%';
SELECT #sql = SUBSTRING(#sql,1, LEN(#sql) - 11);
PRINT(#sql)
EXEC (#sql)
Otherwise, you'll get an error saying:
All queries combined using a UNION, INTERSECT or EXCEPT operator must
have an equal number of expressions in their target lists
Below query might help you :-
DECLARE #SQL VARCHAR(max)
DECLARE #T as sysname
-- Make sure below temporary table structure same as the tables e.g tbl_201602 which you want to union
declare #TT as Table(
Col1 [decimal](18, 2) NOT NULL,
Col2 [date] NOT NULL,
Col3 [varchar](200) NOT NULL
)
DECLARE TName CURSOR FORWARD_ONLY STATIC FOR
select TABLE_NAME
from
information_schema.tables where TABLE_NAME like 'tbl_201602%'
OPEN TName
FETCH NEXT FROM TName INTO #T
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #SQL = 'select * from' + ' ' + #T
INSERT INTO #TT
EXEC(#SQL)
FETCH NEXT FROM TName INTO #T
END
CLOSE TName
DEALLOCATE TName
select * from #TT
This will give the union of all tables in a single temporary table #TT
NOTE : Just make sure that all comman tables are having same no of columns and in same ordering, otherwise it may raise error
I am trying to write a windows service, which will send automatic emails. all the tables which require email sending have common columns 'templateid' and 'emailstatus'. I want to iterate through all the tables and get the tables which has column name 'templateid'.
Now that i have the list of tables with column name 'templateid' get the data from each table whose email status is 'false' and save it in a temporary table.
if 'table1' has 4 rows of data, the temporary table should have 4 rows. after iterating through the next table the row collection should be added to the same temporary table.
IF (SELECT object_id('TempDB..#TEMPTABLE')) IS NOT NULL
BEGIN
DROP TABLE #TEMPTABLE
END
CREATE TABLE #TEMPTABLE(
[ID] INTEGER IDENTITY(1,1) NOT NULL,
[TABLE_NAME] VARCHAR(1000)
)
INSERT INTO #TEMPTABLE(TABLE_NAME)
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'TEMPLATEID'
SELECT * FROM #TEMPTABLE
DECLARE #ROWCOUNT INT
SET #ROWCOUNT = (SELECT COUNT(ID) FROM #TEMPTABLE)
DECLARE #I INT
SET #I=1
WHILE(#I<=#ROWCOUNT)
BEGIN
DECLARE #TABLENAME VARCHAR(500)
SELECT #TABLENAME=TABLE_NAME FROM #TEMPTABLE WHERE ID=#I
EXEC('SELECT * FROM '+#TABLENAME)
SET #I=#I+1
END
i found the above query which is giving me all the tables. after that i am clueless how to proceed further as i am not good with sql server.
Not sure you are still looking for an answer but the following code will give you a temporary table with just the tables that have a column named 'templateid'. From here you would need a cursor as Tanner suggested to loop through each table and then insert records from each table (into your final target table) where email status = 'false'.
Here is the code that gets you the temp tables with columns named 'templateid' along with a sample for your cursor:
declare #max_tables int
declare #max_columns int
declare #sql nvarchar(400)
declare #x int
declare #y int
declare #table varchar(50)
declare #columns varchar(800)
declare #tablename varchar(100)
create table #c ([Table] varchar(50),[Columns] varchar(800))
select ROW_NUMBER() OVER(ORDER BY name) AS Row, name
into #table_list
from sys.objects
where type_desc = 'USER_TABLE'
order by name
set #max_tables = (select count(*) from sys.objects where type_desc = 'USER_TABLE')
set #y = 0
while #y < #max_tables
begin
set #y = #y + 1
set #table = (select name from #table_list where row = #y)
create table #t (c int)
set #sql = 'select count(*) as c from Information_schema.Columns where table_name = ''' + #table + ''''
insert into #t exec sp_executesql #sql
set #max_columns = (select top 1 c from #t)
DROP TABLE #t
set #x = 0
set #columns = ''
while #x < #max_columns
begin
set #x = #x + 1
set #columns = #columns + (select column_name from Information_schema.Columns where table_name = #table and ordinal_position = #x)
if #x < #max_columns set #columns = #columns + ', '
end
insert into #c select #table,#columns
end
select * into #tables from #c c
where c.Columns like '%templateid%'
declare my_cursor cursor for
select table from #t
open my_cursor
fetch next from my_cursor into #tablename
while ##fetch_status = 0
begin
--do something here to retrieve your data from each table and
--insert into target table
end
close my_cursor
deallocate my_cursor
DROP TABLE #c,#tables,#table_List
I have tables like lg-010-a..., lg-010-ac..., and so on, I have abc database,
I have a command window:
drop table from abc where Table_Name like 'lg-010-%'
Will this drop all the tables starting with lg-010-?
Try something like this:
declare #sql varchar(max)
declare #tablenames varchar(max)
select #tablenames = coalesce(#tablenames + ', ','') + Table_Name from INFORMATION_SCHEMA.TABLES
where Table_Name like ('lg-010-%')
set #sql = 'drop table ' + #tablenames
exec (#sql)
This queries the INFORMATION_SCHEMA.TABLES table to retrieve table names that match your criteria, then concatenates them together into a comma delimited string.
This string is than added to a 'Drop table ' statement and executed.
Drop table can take multiple comma delimited table names.
(I had originally had this query sys.tables but some research revealed that while they are currently equivalent, the Information_Schema method is quaranteed to work in future versions)
Unfortunately you can't do it like that. One way is:
SELECT 'DROP TABLE ' + name FROM sysobjects WHERE name LIKE '%lg-010-a%' AND [type] IN ('P')
This will just print out the DROP TABLE statement for each table - you can then copy and paste this output and run it. You can just put an EXECUTE in the loop instead of the PRINT, but I've done it this way so you can see what's going on/check the output first.
I had an issue where the accepted answer was not doing anything. I discovered that I had to add the prefix name of the database to the code to get it to work. If your tables are not dbo.tablename try this.
declare #sql varchar(max)
declare #tablenames varchar(max)
SELECT
#tablenames = COALESCE(#tablenames + ', ','') + 'YourDatabaseName.' + Table_Name
FROM
INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME LIKE 'AP2%'
AND (RIGHT(TABLE_NAME, 6) < 201708)
SET #sql = 'drop table ' + #tablenames
EXEC (#sql)
GO
Unfortunately you can't do it like that.
One way is:
DECLARE #TableName NVARCHAR(128)
SELECT TOP 1 #TableName = TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'lg-010-%'
ORDER BY TABLE_NAME ASC
WHILE (##ROWCOUNT > 0)
BEGIN
PRINT 'DROP TABLE [' + #TableName + ']'
SELECT TOP 1 #TableName = TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'lg-010-%'
AND TABLE_NAME > #TableName
ORDER BY TABLE_NAME ASC
END
This will just print out the DROP TABLE statement for each table - you can then copy and paste this output and run it. You can just put an EXECUTE in the loop instead of the PRINT, but I've done it this way so you can see what's going on/check the output first.
CREATE PROCEDURE dbo.drop_MsSqlTables1 #createDate smalldatetime
AS
declare #flag int =1
declare #tname varchar(50)
declare #sql varchar(max)
select row_number() over (order by name) as num, '[dbo].[' + name +']' as table_name into #temp from sys.tables where name like ('EmpInfo_%') and create_date<#createDate
declare #count int = (select count(*) from #temp)
select * from #temp
while #flag <= #count
begin
set #tname = (select table_name from #temp where num = #flag)
set #sql = 'drop table ' + #tname
exec (#sql)
set #flag = #flag+1
end