October 2, 2003 at 10:33 am
Hi,
I have 20 tables in my database and all of them have the same column structure. I am trying to write a select statement, so that I can query all the tables at once and return matching records. Is it possible? If so can anyone help me out with an example.
thanks in advance,
v
October 2, 2003 at 11:31 am
There's an undocumented Stored Procedure that can help:
This is from The Guru's Guide to Transact-SQL by Ken Henderson.
Procedure:
Sp_MSforeachtable
@command1
@replacechar = '?'
[,@command2]
[,@command3]
[,@whereand]
[,@precommand]
[,@postcommand]
Purpose:
Execute up to three commands for every table in a database (optionally matching the @whereand clause) @replacechar will be replaced with the name of each table. @precommand and @postcommand can be used to direct commands to a single result set.
Example:
EXEC sp_MSforeachtable @command1 = 'PRINT "Listing ?=', @command2='SELECT * FROM ?', @whereand=' AND name like "title%"'
-SQLBill
October 2, 2003 at 1:02 pm
Thank you SQLBill for responding, I would have never found that "undocumented" stored procedure.
I tried executing it, the sp_MSforeachtable runs fines if I am only using select. For example:
exec sp_MSforeachtable @command1 = 'select col_name, col_date from ? "
but I get Server: Msg 207 error if I add the following line:
,@whereand = ' and datepart(year,col_date) = "2003"'
any ideas??
thank you once again,
v
October 2, 2003 at 1:25 pm
Is this how it looks when you added the whereand?
exec sp_MSforeachtable @command1 = 'select col_name, col_date from ?',@whereand = ' and datepart(year,col_date) = "2003"'
-SQLBill
October 2, 2003 at 1:34 pm
thats exactly how it looks like when I type everything together. When I execute I get the following 4 lines of error messages:
Server: Msg 207, Level 16, State 3, Line 1
Invalid column name 'col_date'
Server: Msg 207, Level 16, State 1, Line 1
Invalid column name '2003'
October 2, 2003 at 3:08 pm
looks like I have found a solutions for this problem (or atleast a work around). I tried the following and it worked.
exec sp_MSforeachtable @command1 = ' select col_name, col_date ? where datepart(year,col_date) = 2003'
one strange phenomena though is if I typed 2003 as "2003" (enclosed in double quotes) then it gets back and gives me an error saying
Server: Msg 207, Level 16, State 3, Line 1
Invalid column name '2003'.
Any thoughts????
thanks for your help SQLBill,
V
October 3, 2003 at 2:31 am
Hi,
If you use "", [], {}... SQL sever translates it as a column. This is done because if you have a more than one word field name, or the field name containts characters other than _, 0 to 9, A to Z then you have to access it by enclosing it in a "", [] and so on pair, for example
SELECT [my Result]
FROM Tests
The only way to write a valid SQL string literal is by using single quotes or N and simple quotes if you want to to handle nchar, nvarvar or ntext columns
October 3, 2003 at 7:50 am
I can't figure out what could be wrong. That's directly from the book. You can even find the actual sp in Enterprise Manager (go to Master database, expand it, click on Stored Procedures and find MSforeachtable).
You might try 'toggling' SET QUOTED_IDENTIFIER on and off. Try it each way and see if it makes a difference.
-SQLBill
October 3, 2003 at 8:26 am
Seems like you should just use a "union" query ...
Select * From table1
Union
Select * From table2
Union
...
Select * From table20
October 3, 2003 at 9:19 am
Yea, what dinner said. A union query is the way to go for this. Using sp_msforeachtable will return multiple recordsets - using a union query will return only one recordset (making it look like you queried one table).. you could also create a view from a generic select * from tablea union select * from tableb and use that as a table.
-Ken
October 3, 2003 at 12:00 pm
If I recall correctly, you can use UNION ALL instead of UNION and it should increase your performance slightly.
-Aaron
October 3, 2003 at 2:20 pm
quote:
If I recall correctly, you can use UNION ALL instead of UNION and it should increase your performance slightly.-Aaron
October 3, 2003 at 2:24 pm
Is there a way, in this process, to add a column which inserts in each record the name of the table from which it came?
--Paul
October 3, 2003 at 2:47 pm
A cheap way to do it would be in the union statement:
SELECT Table = "Table1", * FROM Table1
UNION
SELECT Table = "Table2", * FROM Table2
UNION
SELECT Table = "Table3", * FROM Table3
Not sure it that was what you were looking for.
October 3, 2003 at 5:22 pm
Thanks, that would work (with ' instead of "), but actually, with many hundreds of identically structured tables, I was hoping for a way to insert each source table name automatically. I see that when I run just plain...
SELECT * FROM table1
UNION ALL
SELECT * FROM table2
UNION ALL
SELECT * FROM table3
... the result includes a column "tablename", but all the values I get in this column are NULL. Is there something I can do to get the table names (table1, table2, table3, etc.) to populate automatically in this column?
Thanks, Paul
Viewing 15 posts - 1 through 15 (of 29 total)
You must be logged in to reply to this topic. Login to reply