Using temp tables in SSIS - sql-server

I've created an ADO.NET connection manager, and a DataReader source with the following SQL Command:
select
'test' as testcol
INTO
#tmp
select * from #tmp
If I click the refresh button in the DataReader component, I get SqlException "Invalid object name #tmp". The SQL statment itself is clearly valid and executes properly in sql server management studio. I've also tried setting DelayValidation on the connection manager, to no avail.

is the error on the INSERT or the SELECT?
if you are issuing only one command that contains both the INSERT and SELECT, try putting a semicolon before the SELECT.
EDIT after OP comment
encapsulate all the logic within a stored procedure:
CREATE PROCEDURE YourProcedureName
AS
select
'test' as testcol
INTO
#tmp
select * from #tmp
GO
the have your application run this single SQL command:
exec YourProcedureName
EDIT after next OP comment
OP doesn't say which SQL Server version they are using, if 2005 or up, try a CTE:
;with CTEtemp as
(
select
'test' as testcol
)
select * from CTEtemp

Why couldn't this be replaced with a "SELECT 'test' as testcol"? The SSIS query parser may be having trouble with it because there's a temp table involved and it expects a single statement, not an actual SQL script. Or, if what you're sharing above is only an example for illustration, maybe something like this:
SELECT *
FROM (SELECT 'test' AS testcol)
Can you elaborate on what you're trying to accomplish here and, if it is, why the temp table is required?

Use sp_executesql
Your command would become
exec sp_executesql #statement=N'
select
''test'' as testcol
INTO
#tmp
select * from #tmp'
You must use nvarchar string (hence the N), and escape single quotes by doubling them.
I had the same problem as you and this is how I just fixed it.

Related

Why is the table inside a non-met IF being validated before condition is met, resulting in error if table does not exist?

I am trying to execute a procedure with a parameter, and depending on the value of the parameter, three different IF conditions will be evaluated to verify which query it will execute from a linked server.
But when I execute the query, it seems to be checking if the tables inside all the IF exists before starting the query. And I know that only one of the table exists, that is why I am using the parameter, so it shouldn't fail. but I anyhow get the following error:
Msg 7314, Level 16, State 1, Line 25
The OLE DB provider "Microsoft.ACE.OLEDB.16.0" for linked server "LinkedServer" does not contain the table "D100". The table either does not exist or the current user does not have permissions on that table.
So in this code, assume that the parameter is 300. then I get the message above.
Do you know, if there is a way, to limit the query to do not check all the tables, but only the one where the IF condition will be met?
ALTER PROCEDURE[dbo].[Import_data]
#p1 int = 0
AS
BEGIN
SET NOCOUNT ON;
IF(#p1 = 100)
BEGIN
DROP TABLE IF EXISTS Table1
SELECT [Field1], [Field2], [Field3], [Field4], [Field5], [Field6]
INTO Table1
FROM[LinkedServer]...[D100]
END
IF(#p1 = 200)
BEGIN
DROP TABLE IF EXISTS Table2
SELECT[Field1], [Field2], [Field3], [Field4], [Field5], [Field6]
INTO Table2
FROM[LinkedServer]...[D200]
END
IF(#p1 = 300)
BEGIN
DROP TABLE IF EXISTS Table3
SELECT[Field1], [Field2], [Field3], [Field4], [Field5], [Field6]
INTO Table3
FROM[LinkedServer]...[D300]
END
END
I have tried googling it, but I found mostly workarounds as running a sub procedure, but it is not really a clean solution, I think.
Okay, it seems I that I found the answer. Even with an IF statement, the SQL Server validates the entire query before executing it, so the way to overcome it, is to use a Dynamic SQL Query.
"SQL Server Dynamic SQL is a programming technique that allows you to construct SQL statements dynamically at runtime. It allows you to create more general purpose and flexible SQL statement because the full text of the SQL statements may be unknown at compilation."
This is how the query looks now. so instead of multiple IF statements, the query changes dynamically depending on the parameter.
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = N'DROP TABLE IF EXISTS Table1;
SELECT [Field1]
,[Field2]
,[Field3]
,[Field4]
,[Field5]
,[Field6]
INTO Table1
FROM [LinkedServer]...[D' + CONVERT(nvarchar(3),#p1) + N']'
EXEC sp_executesql #SQL

MS SQL "SELECT INTO" table creation issues

I need to modify an MS SQL "job" and add a step. I am creating the step in SSMS to test what I am doing. I am on a DEV server.
I need to do a SELECT INTO to create or populate a table. The only complication is that the FROM clause references a "Linked Server" that is Oracle. The basic query is:
SELECT *
INTO MyDatabase.MySchema.MyTable
FROM LinkedServer..RemoteSchema.RemoteTable
I get two errors reported in SSMS:
No matter what I call the "new" local table SSMS reports that it is an invalid object.
I am told that there is a syntax error near FROM
In the existing DB job there are several examples of this sort of usage. I am just not sure why it is failing here.
What have I tried? I have tried the following in SSMS on my desktop and RDP'd into the DEV server as an 'admin' user to use SSMS there.
SELECT *
INTO MyDatabase.MySchema.MyTable
FROM LinkedServer..RemoteSchema.RemoteTable
--
USE MyDatabase;
SELECT *
INTO MySchema.MyTable
FROM LinkedServer..RemoteSchema.RemoteTable
--
SELECT *
INSERT INTO MyDatabase.MySchema.MyTable
FROM OPENQUERY(LinkedServer, '
select * from RemoteSchema.RemoteTable
');
--
SELECT *
INTO MyDatabase.MySchema.foo
FROM MyDatabase.MySchema.ExistingTable
In the last instance above I am making sure that the source table exists and that the target table does not. I think I am following the rules from HERE
What am I missing?
EDIT
What I was missing was a giant typo. I was actually using incorrect syntax like the third example above: select * INSERT into.... I was blind to the word "INSERT" in my SSMS query window and managed to edit it out of most of the examples above.
You should create an empty table and then insert rows from the linked server into the table.
Create table #MyTable (
col1
, col2 ...
);
INSERT INTO #MyTable (col1, col2 ...)
SELECT col1, col2
FROM LinkedServer..RemoteSchema.RemoteTable

Is it possible to inject sql to delete statement?

i built website that uses sql server and have this sql for deleting items by id that im getting from querystring:
DELETE FROM tablename WHERE GUID = 'param'
is it possible to inject sql that will return db_name() for example?
i know that i can inject sql only for select statements something like this
select name from tablename where 'parems'
union all
select db_name()
but what about delete statements
i know that i can drop table insert to table, but in this stage i need know if i can get kind of data, for ex.: db_name()
Sure. This value of param:
' OR ''='
will result in this statement:
DELETE FROM tablename WHERE GUID ='' OR '' = ''
which will delete all data in the table.
Yes, a query always returns a result, so if the database driver allows it you can simply add another query after the delete.
An input like this:
x'; select db_name() --
would give:
DELETE FROM tablename WHERE GUID = 'x'; select db_name() --'
You should read the wiki & MS docs on SQL Injection
I think your asking if its possible using purely delete statement. If so, its possible by adding the OUTPUT clause like so:
DELETE Sales.ShoppingCartItem
OUTPUT DELETED.*
WHERE ShoppingCartID = 20621;
This will output the deletes rows.
To avoid SQL injections, you should use SQL parameters

How to convert a SQL Server result set to XML after the fact?

Is there a way to cause the result set of a SQL Server stored procedure (or any result set, after the fact) to be encoded in XML format?
I want the result set to be encoded in XML as if the FOR XML RAW clause was used during selection.
However the complex stored procedure logic and its internal SELECT statements should not be modified to return XML because the procedure is used for its standard/non-XML result set most of the time.
Update: Emphasis on the fact I'm looking for an answer in the SQL Server environment - the
results should be returned as if SQL Server has directly encoded them itself, as XML, just like it does when using the built-in XML features like the FOR XML clause.
You would insert the data from the SP into a temp table, then select from that FOR XML
This won't work if the SP itself already does a INSERT .. EXEC SPROC because you cannot nest them
Working examples
use tempdb;
create proc giveme
as
select a = 1, b = GETDATE()
union all
select 2, b = '20100101'
Using INSERT.. EXEC
declare #t table (a int, b datetime)
insert #t
exec giveme
select * from #t for xml raw
Using OPENQUERY
exec sp_addlinkedserver 'localhost'
exec sp_serveroption #server = 'localhost'
,#optname = 'DATA ACCESS'
,#optvalue = 'TRUE'
select *
from openquery(localhost, 'exec tempdb..giveme')
for xml raw
You could try using OPENROWSET in cooperation with FOR XML to do the transformation.
By 'after the fact', do you mean still within the SQL Server environment? Or are you talking about a client program?
Within SQL, you could probably write a sproc that acts as a wrapper for your other sprocs, along these lines. The wrapper sproc would handle the FOR XML work.
In .NET, there are a number of ways to do this.
You can try inserting the result set from the stored procedure into a table variable( or temporary table) and selecting the table rows with the FOR XML clause.
Here is an example:
DECLARE #MyDataTable AS TABLE ( col1 int,...., colN int)
Make sure that the #MyDataTable has the same columns as the stored procedure result set(s).
INSERT INTO #MyDataTable
EXECUTE mysp_GetData #param1=value,....,#paramN;
SELECT * FROM #MyDataTable
FOR XML AUTO

SQL Server 2008: SELECT * INTO TMP from stored procedure

I wish to do the following:
select * into tmptbl from sometable
EXCEPT 'sometable' is a stored procedure that returns a result set AND editing the stored procedure to suit my goal is not an option. ALSO i may or may not know the columns and types of what the procedure returns.
Basically i am looking for a proper way of doing this:
select * into tmptbl from exec someSP
Is this even possible, if so, how?
yes it is possible with a loopback query like this
SELECT * INTO #tmptbl
FROM OPENROWSET ('SQLOLEDB','Server=(local);TRUSTED_CONNECTION=YES;'
,'set fmtonly off exec DatabaseName.dbo.someSP')
More example here: Store The Output Of A Stored Procedure In A Table Without Creating A Table
Be aware that this has to be turned on first, see here: How to enable xp_cmdshell and Ad Hoc Distributed Queries on SQL Server 2005

Resources