Creating a SQL statement based on existing table fields - sql

Having a table populated with databases and table names, is it possible to create some dynamic query based on those fields? Something like:
DECLARE #mysearch NVARCHAR(MAX)= 'SELECT db_name, tbl_name FROM UserConfig where ID = 1';
SELECT * FROM [db_name]..[tbl_name]
Being db_name and tbl_name the result values of #mysearch query.
For clarification, database and table names from where I need to select data are in a table, not hardcoded.
Example:
SELECT * FROM MYDB..MyTable
But "MYDB" and "MyTable" are values stored somewhere else.
Thanks.

I am reading a lot through the lines here, but are you actually after this?
DECLARE #SQL nvarchar(MAX);
DECLARE #CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SELECT #SQL = N'SELECT *' + #CRLF +
N'FROM ' + QUOTENAME(db_name) + N'.dbo.' + QUOTENAME(tbl_name) + N';'
FROM UserConfig
WHERE ID = 1;
EXEC sp_executesql #SQL;
This assumes a single row would be returned for a single value of ID in the table UserConfig.

Related

Use SQL Statement With String

I have a products table and i need to concat my string and my sql statements. Is there any way?
My purpose is that i want to define column names just one time in a string variable and i will use it alot of times. Otherwise my sql statements has alot of column name and it complex my code.
For example, i use this
DECLARE #MyStr NVARCHAR(MAX) = 'ProdId,ProdName'
SELECT TOP 10 #MyStr FROM Products
Result is here
But i need the result as this.
You'll need to use dynamic SQL here. I also suggest you fix your design and don't store delimited data, and ideally use a table type parameter. This would look like the following:
DECLARE #Columns table (ColumnName sysname);
INSERT INTO #Columns (ColumnName)
VALUES(N'Column1'),(N'Column2');
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = NCHAR(13) + NCHAR(10);
SELECT #SQL = N'SELECT ' + STRING_AGG(QUOTENAME(ColumnName),N',') + #CRLF +
N'FROM dbo.Products;'
FROM #Columns;
PRINT #SQL; --Your best friend
EXEC sys.sp_executesql #SQL;
If you don't want to use a table type, you can use STRING_SPLIT:
SELECT #SQL = N'SELECT ' + STRING_AGG(QUOTENAME([Value]),N',') + #CRLF +
N'FROM dbo.Products;'
FROM STRING_SPLIT(#Columns,',');

SELECT INTO dynamic temp table using procedure with dynamic parameter

I can't find a full solution to my problem. I have an existing stored procedure that takes dynamic input as a parameter value. I need to execute this procedure (with a dynamic variable) and would like to somehow SELECT * INTO #mytable without having to declare the schema of the temp table.
I've tried using OPENROWSET but it doesn't allow me to specify the variable (only hard-code it):
select * into #table from openrowset('SQLNCLI', 'Server=localhost;Trusted_Connection=yes;', 'exec SERVER..MYSTOREDPROCEDURE #parameter = 123')
The only other way I'm aware of is wrapping it in a string and using EXEC(#sql), but I can't figure out how to "SELECT * INTO #table" from that.
What are my options? Can I create a UDF table function that can return a dynamic table? Doubtful...
I'm guessing here, but you'll need to do the whole thing in dynamic SQL. So, instead, something like:
DECLARE #SQL nvarchar(MAX);
DECLARE #param nvarchar(10) = 123;
SET #SQL = N'SELECT *' + NCHAR(10) +
N'INTO #table' + NCHAR(10) +
N'FROM OPENROWSET(''SQLNCLI'', ''Server=localhost;Trusted_Connection=yes;'', ''exec SERVER..MYSTOREDPROCEDURE #parameter = ' + QUOTENAME(#param,N'''') +N''');' + NCHAR(10) +
N'SELECT *' + NCHAR(10) + --Of course, I assume you're doing something more complex that a SELECT *.
N'FROM #table;';
PRINT #SQL;
EXEC sp_executesql #SQL;
I think I figured it out. I really only had to modify the temp variable names to put the temp table into the global scope. This works for me with my actual tables (I renamed them for the purposes of this post).
IF OBJECT_ID ('tempdb..##mytemptable') is not null drop table ##mytemptable
declare #id int = 112
declare #sql nvarchar(max) ='SELECT * INTO ##mytemptable FROM OPENROWSET(''SQLNCLI'', ''Server=localhost;Trusted_Connection=yes;'', ''exec SERVER..MyStoredProcedure #ID =' + convert(varchar(10), id) + ''')'
-- invokes and inserts into ##mytemptable
exec sp_executesql #sql
-- now I can query from the global scope
select * from ##mytemptable

How to return all values in the first column of a table without specifying column's name?

I need to create a dynamic sql query in order to return all values in the first column of a table. The table's name needs to be a variable #tableName ( i will run this query for multiple tables depending on several conditions). Also, i don't know exactly the first column's name but it is formed out of Id_#tableName .
I need something like below but written dinamically:
select
(select column_name from INFORMATION_SCHEMA.columns where table_Name= #tableName and ordinal_position=1)
from #tableName
Could you please help me? Thank you in advance!
USE AdventureWorks;
GO
DECLARE #ObjectName SYSNAME = 'Sales.SalesOrderHeader';
DECLARE #SQL NVARCHAR(MAX);
SELECT
#SQL = 'SELECT ' + QUOTENAME(name) + ' FROM ' + #ObjectName
FROM
sys.columns
WHERE
object_id = OBJECT_ID(#ObjectName)
AND column_id = 1;
EXEC sp_executesql #SQL;

Dynamic Table Insert TSQL: Insert records into another table where schemas are Mismatched

In an effort to efficiently move records from one table to another I'm struggling to write a T-SQL stored procedure to accomplish this task in a generic manner.
Requirements:
Needs to be generic so that the specific columns are NOT hard coded into the Stored Procedure.
The only input parameters should be the names of the Source Table and Destination Table.
All Records from Source are Inserted Into Destination
For a given record we map over only the data from the matching columns from both tables
Columns missing from the source table will receive their Default Values in the Destination Table.
Data from any columns missing from the Destination table will simply be ignored
There is one stackoverflow question similar to this, but they were trying to insert into staging tables based on the value of some datetime. I felt it was necessary to post this as an original question since this would be a completely generic solution with no special conditions attached.
I know the solution will involve using Insert Into, any help is greatly appreciated. Thank you.
You could use this as a starting point for your stored proc:
DECLARE #SourceSchema SYSNAME = 'dbo' --Assume dbo for demo purposes.
DECLARE #SourceTable SYSNAME = 'SourceTableName'
DECLARE #DestSchema SYSNAME = 'dbo' --Assume dbo for demo purposes.
DECLARE #DestTable SYSNAME = 'DestinationTableName'
DECLARE #Tsql NVARCHAR(MAX) = ''
DECLARE #Columns NVARCHAR(MAX) = ''
SELECT #Columns = #Columns + '[' + src.COLUMN_NAME + '],'
FROM INFORMATION_SCHEMA.COLUMNS src
JOIN INFORMATION_SCHEMA.COLUMNS dest
ON src.COLUMN_NAME = dest.COLUMN_NAME
--Assume you only want to insert data from src fields to dest fields if they're the same data type.
--Data conversion is messy and outside the scope of the OP's question.
AND src.DATA_TYPE = dest.DATA_TYPE
WHERE src.TABLE_SCHEMA = #SourceSchema
AND src.TABLE_NAME = #SourceTable
AND dest.TABLE_SCHEMA = #DestSchema
AND dest.TABLE_NAME = #DestTable
SET #Columns = LEFT(#Columns, LEN(#Columns) - 1)
PRINT #Columns
SET #Tsql = 'INSERT INTO [' + #DestSchema + '].[' + #DestTable + ']' +
'(' + #Columns + ')' +
'SELECT ' + #Columns +
'FROM [' + #SourceSchema + '].[' + #SourceTable + ']'
PRINT #Tsql
--Uncomment when ready to proceed.
--EXEC (#TSql)

How to form a table name from concatenating strings in Select Statement in SQL 2012

I want to achieve this -
SELECT * FROM A1234
I have the the ID 1234 saved in another table called Aliases which has two columns Alias,ID with one record like this.
Alias = TestTable, ID = 1234
So I am trying something like this
SELECT * FROM ('A'+ (SELECT ID FROM Aliases WHERE Alias = 'TestTable'))
Any help would be appreciated
You should use dynamic sql.
DECLARE #Q VARCHAR(MAX),#ID INT
SET #ID=(Select DISTINCT ID from Aliases where Alias = 'TestTable') -- CHECK TO RETURN JUST ON RESULT
SET #Q='SELECT * FROM A'+CAST(#ID AS VARCHAR(10))
EXEC(#Q)
You need dynamic SQL for this.
DECLARE #sql NVARCHAR(MAX);
SELECT TOP (1) #sql = N'SELECT * FROM A' + RTRIM(ID) + ';'
FROM dbo.Aliases WHERE Alias = 'TestTable';
EXEC sp_executesql #sql;
To build a set of statements that selects all of them, you can say:
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'
SELECT *, ''A' + RTRIM(ID) + ''' FROM A' + RTRIM(ID) + ';'
FROM dbo.Aliases;
PRINT #sql;
-- EXEC sp_executesql #sql;