Insert data into a table from Open Query with variable - sql

I am trying to using OPENQUERY to pull some data into a table. Here's what my code looks like:
DECLARE #TSQL VARCHAR(MAX)
DECLARE #CD VARCHAR(10) = 'XX'
DECLARE #OracleData TABLE (Cd VARCHAR(20), ApptDATE Datetime )
INSERT INTO #OracleData(Cd,ApptDATE )
SELECT #TSQL = 'SELECT * FROM OPENQUERY(LinkedServer,''Select p.Cd, p.AppDate
from ta.table1 p
where p.IdCode = ''''' + #CD + ''''''')'
EXEC (#TSQL)
I end up with the following error:
An INSERT statement cannot contain a SELECT statement that assigns
values to a variable.
When I attempt to run the EXEC(#TSQL) without the INSERT it works like a charm, but I am unable to do an insert.
Any ideas how I can possibly resolve this?
Thanks.

You are doing this the wrong way round.
Don't insert the #TSQL variable into your table, set the variable, then insert the results using INSERT...EXEC...
DECLARE #TSQL nvarchar(max) = '
SELECT *
FROM OPENQUERY(LinkedServer,
''Select p.Cd, p.AppDate
from ta.table1 p
where p.IdCode = ''''' + #CD + ''''''')
';
INSERT INTO #OracleData (Cd, ApptDATE)
EXEC (#TSQL);
I'm sure there is an excellent reason you are not just using a straight Linked Server query without dynamic SQL, but I can't think of one.

Related

SQL Server Linked Server INSERT INTO

I have problem with linked server at store procedure, I want to get data from linked server then insert into table.
This is my stored procedure:
CREATE PROCEDURE [dbo].[SP_GETPRODRECORD]
#PR_NO varchar(10)=''
AS
BEGIN
DECLARE #OPENQUERY nvarchar(4000),
#TSQL nvarchar(4000),
#LinkedServer nvarchar(4000)
CREATE TABLE AAA (PR varchar(10))
SET #LinkedServer = 'LS'
SET #OPENQUERY = 'INSERT INTO AAA SELECT * FROM OPENQUERY('+ #LinkedServer + ','''
SET #TSQL = 'SELECT PSHN9G FROM F9G00 WHERE PSHN9G='''''+#PR_NO+''''')'
EXEC (#OPENQUERY+#TSQL)
END
My problem is that the EXEC is not running, when I try to insert manually with code below is working
INSERT INTO AAA(PR)
SELECT PSHN9G
FROM OPENQUERY(WAVEDLIB,'SELECT PSHN9G FROM F9G00 WHERE PSHN9G=''XXXXXXX'')
Am I missing something?
Thanks
There is no need to use OPENQUERY and EXECUTE, you can simply reference LinkedServer if you know which DB is your table into:
CREATE PROCEDURE [dbo].[SP_GETPRODRECORD]
#PR_NO varchar(10)=''
AS
BEGIN
--No need to CREATE TABLE every time you exec SP. SELECT INTO #temp table instead.
SELECT PSHN9G INTO #temp FROM WAVEDLIB.DBName.dbo.F9G00 WHERE PSHN9G=#PR_NO
SELECT * FROM #temp
END

Stored procedure to find number of rows in a table

In a stored procedure I pass a table name as the input variable.
I want to return the number of rows of this table with that stored procedure.
I tried something like this but it did not work:
declare #maxRowCount bigint
exec('set '+ #maxRowCount + ' =(select COUNT(1) from ' + #tableName + ')')
This is SQL Server 2008.
You can try this
CREATE PROCEDURE dbo.sp_selectcount
#tablename NVARCHAR(200)
AS
DECLARE #cmd NVARCHAR (255)
SET #cmd = 'SELECT count(*) from ' + #tablename
EXEC sp_executesql #cmd
The following example should give you something to work with.
-- fully qualify your table name (this is probably an input value in your sproc?)
-- please note that I use system view master.sys.tables as an example table here
DECLARE #tablename NVARCHAR(MAX) = N'[master].[sys].[tables]';
-- build the sql statement that you will execute
DECLARE #sql NVARCHAR(MAX) = N'SELECT COUNT(*) FROM ' + #tablename;
-- create a variable to hold the number of rows later on
DECLARE #nrofrows BIGINT;
-- create a temp table to store the result of executing the sql statement
CREATE TABLE #temp (NrOfRows BIGINT);
-- insert the result of the execution of the sql statement into the temp table
INSERT INTO #temp
EXECUTE(#sql);
-- extract the number of rows from the temp table
SET #nrofrows = (SELECT NrOfRows FROM #temp);
-- check the result so you can test!
PRINT #nrofrows;
If you want good background information on dynamic SQL, check out Erland Sommarskogs article The Curse and Blessings of Dynamic SQL.
You should remove the quotes around #maxRowCount.
Try this:
declare #maxRowCount bigint
exec('set #maxRowCount =(select COUNT(*) from ' + #tableName + ')')
OR
exec('SELECT #maxRowCount = COUNT(*) from ' + #tableName)
Analysis:
With the query you tried, it will execute:
set blablabla = (select count(1) from MyTable)
By removing the quotes:
set #maxRowCount = (select count(*) from MyTable)
You can try this instead.
declare #maxRowCount bigint(5)
exec('SELECT COUNT(*) INTO #maxRowCount FROM ' + #tableName)

Run SQL pre-defined function stored in table

I have a table which stores a SQL predefined function, like CONVERT(VARCHAR(10), '2012-08-21 00:16:41.993', 101) in a row/column. While retrieving the result from table, it should run the function and give the final outcome as "2012-08-21", instead right now it returns the same function statement. I am running select (select RunDate from RunDate) and using SQL server database.
Kindly help!!
You need to use dynamic SQL for this. You can't just nest expressions and have SQL evaluate the output...
DECLARE #x TABLE(sql NVARCHAR(255));
INSERT #x(sql) SELECT N'CONVERT(VARCHAR(10), ''2012-08-21 00:16:41.993'', 101)';
DECLARE #sql NVARCHAR(MAX);
SELECT #sql = N'SELECT ' + sql FROM #x;
EXEC sp_executesql #sql;
It would look like this (adjust accordingly):
DECLARE #predef VARCHAR(1000);
DECLARE #sqlquery VARCHAR(1000);
SELECT #predef = (SELECT top 1 Value FROM Parameters Where Name = 'MYFUNC');
SET #sqlquery = 'select ' + #predef + ' from SomeTable';
EXECUTE ( #sqlquery );
One tip: here be dragons. Beware of SQL Injection.

Execute sp_executeSql for select...into #table but Can't Select out Temp Table Data

Was trying to select...into a temp Table #TempTable in sp_Executedsql.
Not its successfully inserted or not but there Messages there written
(359 row(s) affected) that mean successful inserted?
Script below
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = 'select distinct Coloum1,Coloum2 into #TempTable
from SPCTable with(nolock)
where Convert(varchar(10), Date_Tm, 120) Between #Date_From And #Date_To';
SET #Sql = 'DECLARE #Date_From VARCHAR(10);
DECLARE #Date_To VARCHAR(10);
SET #Date_From = '''+CONVERT(VARCHAR(10),DATEADD(d,DATEDIFF(d,0,GETDATE()),0)-1,120)+''';
SET #Date_To = '''+CONVERT(VARCHAR(10),DATEADD(d,DATEDIFF(d,0,GETDATE()),0)-1,120)+''';
'+ #Sql;
EXECUTE sp_executesql #Sql;
After executed,its return me on messages (359 row(s) affected).
Next when trying to select out the data from #TempTable.
Select * From #TempTable;
Its return me:
Msg 208, Level 16, State 0, Line 2
Invalid object name '#TempTable'.
Suspected its working only the 'select' section only. The insert is not working.
how fix it?
Using a global temporary table in this scenario could cause problems as the table would exist between sessions and may result in some problems using the calling code asynchronously.
A local temporary table can be used if it defined before calling sp_executesql e.g.
CREATE TABLE #tempTable(id int);
execute sp_executesql N'INSERT INTO #tempTable SELECT myId FROM myTable';
SELECT * FROM #tempTable;
Local temporary table #table_name is visible in current session only, global temporary ##table_name tables are visible in all sessions. Both lives until their session is closed.
sp_executesql - creates its own session (maybe word "scope" would be better) so that's why it happens.
In your #sql string, don't insert into #TempTable. Instead, call your SELECT statement without an INSERT statement.
Finally, insert the results into your temporary table like so:
INSERT INTO #tmpTbl EXEC sp_executesql #sql
Also, you'll need to declare the temporary table if you use this approach
DECLARE #tmpTbl TABLE (
//define columns here...
)
your temp table in dynamic SQL is out of scope in the non dynamic SQL part.
Look here how to deal with this: A bit about sql server's local temp tables
Temporary tables only live as long as the connection that creates them. I would expect that you're unintentionally issuing the select on a separate connection. You can test this by momentarily doing your insert into a non-temporary table and seeing if your data is there. If that is the case you can go back to your original solution and just be sure to pass the connection object to your select.
declare #sql varchar(1000)
set #sql="select * into #t from table;"
set #sql =#sql + "select * from #t;"
execute SP_EXECUTESQL #sql
This worked for me
declare #sql nvarchar(max)
create table #temp ( listId int, Name nvarchar(200))
set #sql = 'SELECT top 10 ListId, Name FROM [V12-ListSelector].[dbo].[List]'
insert into #temp
exec sp_executesql #sql
select * from #temp
drop table #temp
To work around this issue use a CREATE TABLE #TEMPTABLE command first to generate an empty temp table before running sp_executesql. Then run the INSERT INTO #TEMPTABLE with sp_executesql. This will work. This is how I overcome this problem as I have a setup in which all my queries are usually run via sp_executesql.
This one worked for me:
DECLARE #Query as NVARCHAR(MAX);
SET #Query=(SELECT * FROM MyTable) ;
SET #Query=(SELECT 'SELECT * INTO dbo.TempTable FROM ('+#Query +') MAIN;');
EXEC sp_executesql #Query;
SELECT * INTO #TempTable FROM dbo.TempTable;
DROP TABLE dbo.TempTable;
SELECT * FROM #TempTable;
Note, from T-SQL 2021 onwards, dm_exec_describe_first_result_set() can be used to build a temporary table in the right shape to INSERT INTO - as it gives you the column names and types that will be returned from your dynamic SELECT or EXEC ... so you can build dynamic SQL to ALTER a temporary table into the shape you need.
DECLARE #strSQL NVarChar(max) = 'EXEC [YourSP] #dtAsAt=''2022-11-09'', #intParameter2=42'
--*** Build temporary table: create it with dummy column, add columns dynamically
--*** using an exec of sys.dm_exec_describe_first_result_set() and dropping the dummy column
DROP TABLE IF EXISTS #tblResults;
CREATE TABLE #tblResults ([zz] INT);
DECLARE #strUpdateSQL NVarChar(max);
SELECT #strUpdateSQL = STRING_AGG( CONCAT( 'ALTER TABLE #tblResults ADD ',
QUOTENAME([name]), ' ',
[system_type_name], ';')
, ' ') WITHIN GROUP (ORDER BY [column_ordinal])
FROM sys.dm_exec_describe_first_result_set (#strSQL, NULL, 0)
SET #strUpdateSQL += 'ALTER TABLE #tblResults DROP COLUMN [zz];'
EXEC (#strUpdateSQL);
--*** Now we have #tblResults in the right shape to insert into, and use afterwards
INSERT INTO #tblResults EXEC (#strSQL);
SELECT * FROM #tblResults;
--*** And tidy up
DROP TABLE IF EXISTS #tblResults;

How to specify a table dynamically in a Stored Procedure

Thanks for the feedback, but I was hoping for help with an UPDATE command, not SELECT.
Can anyone help with the syntax for an UPDATE command?
I am passing a table name into a Stored Procedure but the SQL does not seem to recognize it.
DECLARE #userTable AS VARCHAR(200);
SET #userTable = #currTable
UPDATE #userTable
SET [lang_String] = #lang_String, [date_Changed] = #submitDate1
WHERE (ID = #ID)
#currTable is passed into the Stored Procedure. All tables names are built by design in code.
You can't, you need to build the entire SQL string and then execute it, like this for example:
DECLARE #sql nvarchar(4000)
SELECT #sql = ' SELECT col1, col2, col3 ' +
' FROM dbo.' + quotename(#tblname) +
' WHERE keycol = #key'
EXEC sp_executesql #sql, N'#key varchar(10)', #key
Got this to work quite easily....
#myTable varchar(150)
/* Comments:
*/
AS
SET NOCOUNT ON;
DECLARE #sql varchar(max);
SET #sql = 'SELECT [ID], [StringID], [GUID] FROM ' + #myTable + ' ORDER BY [GUID]';
print (#sql)
EXECUTE(#sql);
SET #langTable = Null;
FYI, the values available for myTable are stored in another table and are not available to users for edit. Table names are built dynamically in code based on a unique combination of values.