Insert Temp Table Failing with Parsing Error on Exec - sql-server

I want to insert the result set coming from a query into a temporary table in Azure SQL Data Warehouse. I used the below statements but I am getting a parse error:
DECLARE #SQL2 NVARCHAR(1000)
CREATE taBLE #TempTable (L NVARCHAR(100))
SET #SQL2 = 'SELECT Col1 FROM Table1'
INSERT INTO #TempTable (L) EXEC SQL2***
Msg 103010, Level 16, State 1, Line 44
Parse error at line: 5, column: 28: Incorrect syntax near 'EXEC'.
I even tried Declare #T TABLE (ID iNT) still getting a parse error.

I got answer minutes after uploading the question
Azure SQL Data Warehouse does not support INSERT ... EXEC
For explanation and an alternative approach: https://learn.microsoft.com/en-gb/azure/sql-data-warehouse/sql-data-warehouse-develop-stored-procedures#insertexecute

Related

Dynamic equivalent of INSERT INTO using EXEC

I am trying to create the equivalent of the following:
DROP TABLE IF EXISTS [jerry].[dbo].[purchases]
SELECT * INTO [jerry].[dbo].[purchases] FROM OPENQUERY(OLAP, '
sql code
');
usingEXEC(see this question here)
With that being said, I am unable to use SELECT * INTO according to multiple sources (and this one)
I have found some other resources where I can create a new table using EXEC, however, I do not know the exact structure of the resulting table (number of columns, column types, column names, etc) so it needs to be dynamic.
The following code results in giving me the exact resulting table that I want, but I have not been able to figure out how to create the purchases table with the resulting data from the below query:
-- EXEC master.dbo.sp_serveroption #server=N'OLAP', #optname=N'rpc out', #optvalue=N'true'
DECLARE #sqlcode VARCHAR(MAX)
SET #sqlcode = 'code'
EXEC (#sqlcode) AT OLAP
I have tried using the following: SELECT * INTO [jerry].[dbo].[purchases] FROM OPENROWSET('EXEC (#sqlcode) AT OLAP') but get an error of Incorrect syntax near ')'.
I have also tried (just to see):
CREATE TABLE [jerry].[dbo].[purchases] ([Transaction_Date] DATE, [Requirement_Date] DATE, [Element] NVARCHAR(256), [Trx_Quantity] NVARCHAR(256), [Part_Number] NVARCHAR(256), [NHA_Part_Number] NVARCHAR(256), [Group] NVARCHAR(256), [Details] NVARCHAR(256));
INSERT INTO [jerry].[dbo].[purchases]
EXEC (#sqlcode) AT OLAP
And get an:
OLE DB provider "OraOLEDB.Oracle" for linked server "OLAP" returned message "Unable to enlist in the transaction.".
Msg 7391, Level 16, State 2, Line 208
The operation could not be performed because OLE DB provider "OraOLEDB.Oracle" for linked server "OLAP" was unable to begin a distributed transaction.
error.
Apologies if this is an easy logic question -- I feel like I am exhausting my researching ability trying to find a solution as I am very new to SQL Server. I am working in SSMS 2017, as well, if that helps.
The answer can be found at this post:
Create new table with results from EXEC
DECLARE #sqlcode VARCHAR(MAX)
SET #sqlcode = 'sqlcode'
truncate table [jerry].[dbo].[purchases]
insert into [jerry].[dbo].[purchases]
exec ( #sqlcode ) at OLAP

SQL, cursor for one time initialization, Must declare scalar variable

I am using a cursor to one time populate a table with all tenants that are in the tenants table. I want to make sure that the tenantId will be set with a name of General in my navigations table. But for some reason it thinks that my variable isn't set.
I tried the following code
**** Script for SelectTopNRows command from SSMS ******/
declare #tenantId int
declare #tenantName nvarchar(100)
DECLARE tenantCursor CURSOR FOR
SELECT Id, [Name]
FROM [dbo].[Tenant]
OPEN tenantCursor;
FETCH NEXT FROM tenantCursor INTO #tenantId, #tenantName;
WHILE ##FETCH_STATUS = 0
BEGIN
print #tenantId
print #tenantName
SET #tenantId = #tenantId
Insert INTO [dbo].Navigations ([Name, TenantId])
VALUES ('Algemeen', #tenantId);
GO
FETCH NEXT FROM tenantCursor INTO #tenantId, #tenantName;
END;
CLOSE tenantCursor;
DEALLOCATE tenantCursor;
GO
I got the follwoing error:
Msg 102, Level 15, State 1, Line 22
Incorrect syntax near ';'.
Msg 137, Level 15, State 2, Line 26
Must declare the scalar variable "#tenantId".
The structure of my tables
Any help will be much appreciated.
Rodney
The simple solution is to just use SQL in the set based manner with which it is designed and run the following instead of your cursor:
insert into dbo.Navigations ([Name]
,TenantId
)
select 'Algemeen'
,Id
from dbo.Tenant;
Outside of the above however, you shouldn't have a go in the middle of your cursor and you have missed some square brackets on your insert:
Insert INTO [dbo].Navigations ([Name, TenantId])
should be
Insert INTO [dbo].Navigations ([Name], [TenantId])

Insert stored procedure data in a temp table in SQL Server

I am trying to insert the data of a stored procedure into a temp table like below
CREATE TABLE #CustomTable3HTML
(
ItemId varchar(30),
ItemId1 varchar(30)
)
INSERT INTO #CustomTable3HTML
EXEC SalesDeals.dbo.prGetDealProposalDetail 17100102, 1
but I am getting this error
Msg 8164, Level 16, State 1, Procedure prGetDealProposalDetail, Line 138 [Batch Start Line 1]
An INSERT EXEC statement cannot be nested.
I figured this is because the stored procedure already has an insert into clause defined and I found out that it can be used only once in the calling chain.
So I started looking for other options and found out about OpenRowSet which I am using as below
SELECT *
INTO #CustomTable3HTML
FROM OPENROWSET('SQLOLEDB','Server=Demo\Demo;Trusted_Connection=Yes;Database=SalesDeals',
'SET NOCOUNT ON;SET FMTONLY OFF;EXEC SalesDeals.dbo.prGetDealProposalDetail 17100102,1')
I am getting an error when I run this SQL command
Access to the remote server is denied because no login-mapping exists.
It works fine when I use a higher level account like sysadmin but fails with the other account which is a normal db owner on the database where I am running this SQL.
There is work around of this. It's not beautiful, but it will work.
In our outer query define a table:
CREATE TABLE #CustomTable3HTML
(
ItemId varchar(30),
ItemId1 varchar(30)
)
Change the procedure adding the following code at the end:
IF OBJECT_ID('tempdb..#CustomTable3HTML')
BEGIN
INSERT INTO #CustomTable3HTML
SELECT ....
END
ELSE
BEGIN
SELECT ....
END
After executing the stored procedure you will have the data in table.

T-SQL: putting results of stored procedure into a temp table when you have a timestamp column and can't hardcode column names

For my SQL Server unit tests, I am trying to suppress returning all rows when counting results of a "get all rows" stored procedures. To this end I am trying to write the results to a temp table.
I begin with a linked server entry pointing to the current server and database.
IF NOT EXISTS (SELECT * FROM sys.servers WHERE NAME = 'DB_LOCAL')
BEGIN
DECLARE #DBNAME VARCHAR(MAX) = (SELECT DB_NAME())
EXEC sp_addlinkedserver #server = 'DB_LOCAL', #srvproduct = '', #provider = 'SQLOLEDB', #datasrc = ##servername, #catalog=#DBNAME
END
This is so that I can use OPENQUERY to create a temp table with the output structure of the stored procedure on the fly without having to hard code the columns.
IF OBJECT_ID('tempdb..#ut_results') IS NOT NULL
DROP TABLE #ut_results
SELECT *
INTO #ut_results
FROM OPENQUERY (DB_LOCAL, 'EXEC p_AnzLookup_get #id = 0')
I want to use this temp table to exec my stored procs into, I can't use OPENQUERY again because I need to specify variables as part of the test. Also, the unit test is in a transaction and doing so creates locking issues. Once I have the structure I do this. I can't specify the column names without the timestamp column which I appreciate would work as they could be changed by 3rd parties.
TRUNCATE TABLE #ut_results
INSERT INTO #ut_results
EXEC p_AnzLookup_get #id = #record_id
This insert into is failing because I have a timestamp column returned by the stored procedure.
Msg 273, Level 16, State 1, Line 2
Cannot insert an explicit value into a timestamp column. Use INSERT with a column list to exclude the timestamp column, or insert a DEFAULT into the timestamp column.
I can't change the timestamp column in the temp table due to this error.
ALTER TABLE #ut_results
ALTER COLUMN TStamp BINARY(8)
Msg 4928, Level 16, State 1, Line 5
Cannot alter column 'TStamp' because it is 'timestamp'.
I can't drop and recreate the timestamp column in the temp table because it changes the column order.
ALTER TABLE #ut_results DROP COLUMN TStamp
ALTER TABLE #ut_results ADD TStamp BINARY(8)
Which leads to different errors when data inserts into the wrong columns:
Msg 257, Level 16, State 3, Procedure p_AnzLookup_get, Line 20
Implicit conversion from data type datetime to int is not allowed. Use the CONVERT function to run this query.
I can't make changes to stored procs these unit tests are for and I can't hard code the column names. I need to write this in a way that is both resilient an reactive to changes outside of my control.
This is just a small subset of one of the unit tests that I have extracted to demonstrate this problem. Any thoughts as to how I get round this sticky bit?
I think I have something that will work. Create temp table using OPENQUERY then mash that through XML to get a csv list of column names into a varchar. Then do a replace on this to cast the timestamp column as varbinary(8).
Using the column list from the above I can select the structure of my first temp table into the second with the fields in the correct order and the timestamp column defined as varbinary(8) that can accept timestamp data.
It isnt pretty tho:
IF OBJECT_ID('tempdb..#ut_results') IS NOT NULL DROP TABLE #ut_results
IF OBJECT_ID('tempdb..#ut_results2') IS NOT NULL DROP TABLE #ut_results2
SELECT * INTO #ut_results2
FROM OPENQUERY ( DB_LOCAL ,'EXEC p_AnzLookup_get #id=-1' )
DECLARE #cols VARCHAR(MAX) = ''
SELECT #cols = Stuff(( select ',' + name from tempdb.sys.columns where object_id =
object_id('tempdb..#ut_results2')
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '')
SET #cols = REPLACE(#cols,'TStamp','CAST(TStamp AS VARBINARY(8)) AS TStamp')
DECLARE #SQl VARCHAR(MAX) = 'SELECT ' + #cols + ' INTO #ut_results FROM #ut_results2 WHERE 1=2'
EXEC (#SQl)
IF OBJECT_ID('tempdb..#ut_results2') IS NOT NULL DROP TABLE #ut_results2
EDIT:
One slight change to this. In the above I create the final temp table in dynamic SQL but it was not accessible afterwards. I have changed this to a regular table.
DECLARE #SQl VARCHAR(MAX) = 'SELECT ' + #cols + ' INTO ut_results FROM #ut_results2'
EXECUTE (#SQl)

TSQL insert exec(#command)

I am wondering why below statement is not working:
insert into #temp (ip, ping) values ('ip', exec xp_cmdshell 'ping ip')
I would like to get resultset where I will have ip address in one column and ping from that server. Above query returns errors:
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'exec'.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ')'.
Thanks in advance for explanations.
You can't execute anything in a INSERT statement value list. You need to execute like this:
insert into #temp
execute xp_cmdshell 'ping ip'
[This assumes that the #temp table has a column structure matching the resultset of xp_cmdshell ]
You can also create an intermediate temp table to contain all the columns that the stored procedure returns and then insert just the ones you want into your final table.
Well, insert ... exec is notoriously inflexible. For one thing, it won't work with a values clause. Even more annoyingly, it does not support a column list. The columns in the table have to match the output of the stored procedure exactly.
The only way to use insert ... exec is:
insert TableName exec(...)
-- ^^^--> no column list!
Here's an example:
if exists (select * from tempdb.sys.tables where name like '#temp__%')
drop table #temp
create table #temp (output varchar(max))
insert into #temp execute xp_cmdshell 'ping pong'
select * from #temp

Resources