I'm trying to write a SQL script which pulls the value of a cell in a given table across multiple databases in a single server. The table has the same name and path across several databases. I'd like to list the specific cell values in a new table.
My first step is to pull all of the database names into a temporary table and then concatenate the table path to it. The code I use is
SELECT name
INTO #dbtablepaths
FROM master.dbo.sysdatabases
WHERE name like 'FTR[0-9]%'
UPDATE #dbtablepaths
SET name=CONCAT(name, '.ftrdbo.[File]')
This will create a table of dbo paths that when queried will return the following:
__|__name_____________
1 | FTR108547.ftrdbo.[File]
2 | FTR564187.ftrdbo.[File]
3 | FTR849721.ftrdbo.[File]
I can then pull one of these dbo paths using the following query
SELECT name FROM(
SELECT ROW_NUMBER() OVER (ORDER BY name ASC) as rownumber,
name
FROM #dbtablepaths
) AS foo
WHERE rownumber = 1
This will return the first dbo path in the table which is FTR108547.ftrdbo.[File].
If I simply copy that path into a SELECT statement (see below) it will bring up the table as intended.
SELECT * FROM FTR108547.ftrdbo.[File]
However, if I try to use a subquery to enter that into the FROM clause of a SELECT statement then the query simply returns the dbo path again. E.G.
SELECT * FROM (
SELECT name FROM(
SELECT ROW_NUMBER() OVER (ORDER BY name ASC) as rownumber,
name
FROM #dbtablepaths
) AS foo
WHERE rownumber = 1
)
I would expect this query to pull the File table but instead it just returns the dbo path again. I.E. FTR108547.ftrdbo.[File]
Is there a way to use table cell values to create queries like this? I know the SELECT statement is returning a table and not a string. Is there a way to convert this table value to a string that can be used in a subsequent SELECT query?
you will have to forgive me as i am unable to make comments yet but you will probally want to take a look at the answers in this post
Executing SQL query on multiple databases
it has several examples that will work for you
This will assign the result into a variable #tabname and use it in the SELECT
DECLARE #sql VARCHAR(MAX)
DECLARE #tabname VARCHAR(100)
SELECT name
INTO #dbtablepaths
FROM master.dbo.sysdatabases
WHERE name like 'FTR[0-9]%'
UPDATE #dbtablepaths
SET name=CONCAT(name, '.ftrdbo.[File]')
SELECT #tabname = name
FROM (SELECT ROW_NUMBER() OVER (ORDER BY name ASC) AS rownumber,
name
FROM #dbtablepaths
) AS foo
WHERE rownumber = 1
SET #sql = 'SELECT * FROM ' + #tabname
EXEC(#sql)
Related
I am trying to select all distinct values from all tables that start with a specific name, like: 'logs_2020_12_01', 'logs_2021_01_02', ..To select all tables with this specific name is straight forward:
SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'logs_%';
The select I want for one individual table is:
SELECT DISTINCT batch FROM logs_2021_01_27;
but I cannot find a way to combine it to make the selection from all tables. I tried a couple of things but it does not work, like:
SELECT DISTINCT batch FROM (SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'logs_%')
any ideas?
thanks
What about using Dynamic SQL, stored your tables information into a temp table with id column and set it to identity.
CREATE TABLE #temp ---identity column will be used to iterate
(
id INT IDENTITY,
TableName VARCHAR(20)
)
INSERT INTO #temp
SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'logs_%';
-- choose your own results with where conditions
DECLARE #SQL VARCHAR(MAX)
DECLARE #Count INT = 1
DECLARE #Table VARCHAR(20)
WHILE #COUNT <= (SELECT COUNT(*) FROM #temp)
BEGIN
select #table = TABLENAME FROM #temp WHERE id = #Count
SELECT #sql = 'SELECT DISTINCT(batch) FROM '+ #table
PRINT #SQL
SET #Count = #Count + 1
END
after your print result looks good, change it to EXEC(#SQL), thanks
SQLite does not support dynamic sql.
You have to select the column batch from each of all the tables and combine them with UNION so the duplicates are removed:
SELECT batch FROM logs_2020_12_01 UNION
SELECT batch FROM logs_2020_12_02 UNION
......................................
SELECT batch FROM logs_2020_12_30 UNION
SELECT batch FROM logs_2020_12_31
If you don't know the full names of the tables, you can get them with this statement:
SELECT name
FROM sqlite_master
WHERE type = 'table' AND name LIKE 'logs/_%' ESCAPE '/'
and then use a programming language to construct a SELECT statement with UNION to get the results that you want.
I don't know how to union all tables with dynamic SQL.
The issue is that I'm inserting into db a number of tables - all having the same structure (only one varchar column
[Line]
). I don't know that would be the number of tables inserted - it depends on the project. But I want to automate the process in SQL.
I'm using this query to find those tables, additionally I'm adding some [RowNum] that may serve as an ID of each table:
SELECT
ROW_NUMBER() OVER (ORDER BY Name) AS [RowNum],
[Name] AS [Name]
INTO #all_tables_with_ids
FROM #all_tables
This query returns:
RowNum | Name
------------------------
1 | Table 1
2 | Table 2
3 | Table 3
4 | Table 4
I would like to merge all tables together. I was trying to write some insert into in while loop but it didn't work. I figured out that I need dynamic SQL.
Can you suggest something? I was trying to find some examples but all of them fail due to the fact that the list of tables is not known at the beginning, so it needs to be created dynamically as well.
Demo here:
create table #test
(
RowNum int,
Name varchar(100)
)
insert into #test
select 1,quotename('table1')
union all
select 2,quotename('table2')
declare #sql nvarchar(max)
set #sql='select somecol from tbl union all '
declare #sql1 nvarchar(max)
;with cte
as
(select #sql as ql,name,rplc
from
#test t1
cross apply
(select replace(#sql,'tbl',name) as rplc from #test t2 where t1.rownum=t2.rownum)b
)
select #sql1= stuff(
(select ''+rplc
from cte
for xml path('')
),1,0,'')
set #sql1=substring(#sql1,1,len(#sql1)-10)
print #sql1
--exec(#Sql1)
I am trying to execute sp as sub query and treat result set of sp as column of outer query . Some thing like this
Select U.FirstName , (exec SomeSP ) as columnFromSP from User U
Is this possible i searched alot but found nothing on google.
Update
I cannot use #temp table because i am trying to do without #temp table
If you are able to convert your USP to a table value UDF, you will be use the UDF in your FROM statement.
CREATE FUNCTION dbo.SomeUDF
(
-- Add the parameters for the function here
#param varchar(1000)
)
RETURNS TABLE
AS
RETURN
(
SELECT #param as Value
)
GO
SELECT
a.Value,
'B' as Value2
FROM dbo.SomeUDF('ABC') a
Not possible, but you can work around it
Create a temp table & insert the results of the procedure into
it
Now join the User table with the temporary table and select the
columns you want from both tables
This assumes however, you have a joinable expression returned from the stored proc (one that you can match to a field in the user table). If the stored procedure on returns a single row, use a condition of 1=1 or something similar
-- Declare a temp table and column(for eg you have only 1 column)
CREATE TABLE #TEMP
(
FirstName VARCHAR(50)
)
-- The results after execution will be inserted to this table
INSERT INTO #TEMP
Exec SomeSP 'Params'
-- Select records from both tables in all combinations
SELECT U.FirstName , COL1 as columnFromSP
from User U
CROSS JOIN #TEMP
Is it possible to use a set of query results for column names in a select statement?
Example, I have a table named TableA:
Column: Type:
KeyOne nvarchar(5)
KeyTwo nvarchar(5)
TableB is another table, whose column names might be stored in TableA.
Suppose TableB is like this:
Column: Type:
Val1 int
Val2 int
Is there any way I could do a query like this to get the columns?
SELECT (select TOP 1 KeyOne, KeyTwo FROM TableA)
FROM TableB
Another example using strings would be like this:
SELECT (select 'Val1', 'Val2')
FROM TableB
Is this possible in any way without concatenated SQL?
Unfortunately you can only do this with dynamic SQL, but it's pretty straightforward:
DECLARE #cols VARCHAR(MAX) = (SELECT TOP 1 KeyOne+','+KeyTwo FROM TableA)
,#sql VARCHAR(MAX)
SET #sql = 'SELECT '+#cols+' FROM TableB'
EXEC (#sql)
You can read table column names dynamically from sys.columns system views or using other management views
select name from sys.columns where object_id = object_id(N'TableName')
Then by creating a dynamic SQL query you can create your own select
Error:
Could not find stored procedure 'SELECT TOP 1 name FROM (SELECT TOP 5 name FROM sys.tables ORDER BY name DESC) as t ORDER BY name ASC'.
Code:
WHILE (#interval <= #max)
BEGIN
SET #SQL = 'SELECT TOP 1 name FROM (' +
SELECT TOP ' + convert(varchar(10), #interval) +
' name FROM sys.tables ORDER BY name DESC) as t ORDER BY name ASC'
EXEC #SQL
SELECT #interval = #interval + 1
END
Executing the following command on its own works properly:
SELECT TOP 1 name
FROM
(SELECT TOP 5 name
FROM sys.tables
ORDER BY name DESC) as t
ORDER BY
name ASC
Incrementing the inner TOP # manually and running the command without TSQL will rotate through each table properly. (This will eventually include a nested loop for Column, and another nested loop for a search within that column.)
That the command runs without the variable makes me think this is a scope issue. Shouldn't I be able to resolve this by inserting the list of table names into a temp table with a Primary Key of Seed 1, Increment 1 for a row_id, and then looping through the table via incrementing my #row_id = row_id?
Any suggestions?
It should be exec(#sql), I think