How can I insert text, from a subquery, in a function request - sql

I'm using a function on the Master database (xp_fileexist) to check if a folder is empty or not. If it's empty I want a 0, otherwise a 1.
If I hardcode the folder name ('C:\Import\2016-01-01\Transaction') it works fine. What doesn't work for me, is having the date as a variable, as the date changes from time to time. For the variable, I use this:
'C:\Import\The Netherlands\'+CAST((select workingdate from system..tmpworkingdate) AS VARCHAR(10))+'\Transaction(BP)'
This is the code I've tried:
CREATE TABLE #temp (FileExists int, IsDirectory int, ParentDirExists int)
INSERT INTO #temp
EXEC master..xp_fileexist ('C:\Import\'+CAST((select workingdate from system..tmpworkingdate) AS VARCHAR(10))+'\Transaction(BP)')
IF EXISTS(SELECT IsDirectory FROM #temp WHERE IsDirectory=1)
PRINT 1
ELSE
PRINT 0
DROP TABLE #temp
Error: Msg 102, Level 15, State 1, Line 5 Incorrect syntax near
'C:\Import\The Netherlands\'. Msg 156, Level 15, State 1, Line 5
Incorrect syntax near the keyword 'AS'.
Does anyone have a clue?

EXEC doesn't allow string manipulations (or any expression evaluation). Define the value beforehand:
DECLARE #filename VARCHAR(MAX);
SET #filename = 'C:\Import\'+CAST((select workingdate from system..tmpworkingdate) AS VARCHAR(10))+'\Transaction(BP)';
EXEC master..xp_fileexist (#filename);
That said, you should use CONVERT() or FORMAT() to be sure you get the format you really want. You wouldn't want system changes to totally break this code.
EDIT:
Argg! I didn't realize that EXEC master..xp_fileexist doesn't even allow string variables on the execution line. So, you have to do the whole thing as dynamic SQL:
DECLARE #sql NVARCHAR(MAX) = 'EXEC master..xp_fileexist ''' + #filename + '''';
EXEC(#sql);
(There are examples on the web that do use variables, so maybe this depends on the SQL Server version.)

Related

Dynamic insert sql stored procedure

I have an issue regarding dynamic insert sql stored procedure because i need to insert an unknown amount (dynamically generated),
below is how it's written:
#Parameter as nvarchar(Max),
#SQLQuery as nvarchar(Max)
SET #SQLQuery = 'insert into <table>
(FieldOne,FieldTwo,FieldThree,GeneratedId,dateAdded,addedBy)
values '+#Parameter
EXEC sp_executesql #SQLQuery
When i try to execute this stored procedure using the below values:
#Parameter = (1,0,0,12345678123,"2016-03-22 23:26:25",123)
#SQLQuery = null
I even tried (for silly reasons) to try the below values:
#Parameter = (1,0,0,12345678123,2016-03-22 23:26:25,123)
#SQLQuery = null
I get the below Error from SQL Server
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '23'.
(1 row(s) affected)
But no rows are actually added.
The table i am using is as below:
ID (PK and autoincrement)
FieldOne: tinyint
FieldTwo: tinyint
FieldThree: tinyint
GeneratedId: nvarchar(50)
dateAdded: datetime
addedBy: int
I can't seem to figure out what i am doing wrong,
Thank you all in advance for your time and assistance.
Your date variable should be wrapped in single quotes, not double. Try that and it should work.
BUT.....
If you particularly want to go down this (unusual) road, I'd strongly suggest using the parameterised query support in sp_ExecuteSQL - it'll give you a better performing and usually more secure query.
Have a look https://msdn.microsoft.com/en-us/library/ms188001.aspx for more information on how to use sp_ExecuteSQL for parameterised queries.
If you need the double quotes, be sure that QUOTED_IDENTIFIER is on
ie.
SET QUOTED_IDENTIFIER ON;

OPENQUERY(SERVERNAME, STOREDPROCEDURE) Syntax error

This is my code
DECLARE #stringvariable nvarchar(200) = 'Hello';
DECLARE #sql nvarchar(2000) = SELECT * INTO ##global FROM OPENQUERY(DB1, ''EXEC GETCASE ''' + #stringvariable + ''''')'
Printing #sql returns a correctly formatted query, however SQL Server doesn't like #stringvariable and returns an error
Msg 102, Level 15, State 1, Line 11
Incorrect syntax near 'Hello'.
Here is what the outputted query looks like
SELECT * INTO ##global FROM OPENQUERY(DB1, 'EXEC GETCASE 'Hello'')
How can I avoid this error? It seems like because my stored procedure takes a string parameter, it's throwing off the query. I've read that OPENQUERY does not support variables, but I've parameter the variable so it should work?
Appreciate your help!
The stored procedure exists in a database and a schema. You need to supply those. Supposing database db_name and schema schema_name:
DECLARE #stringvariable nvarchar(200) = 'Hello';
SET #stringvariable=REPLACE(#stringvariable,'''',''''''''''); -- doubly doubled single quotes for the dynamic statement
DECLARE #sql nvarchar(2000) = 'SELECT * INTO ##global FROM OPENQUERY(DB1, ''SET FMTONLY OFF;EXEC db_name.schema_name.GETCASE ''''' + #stringvariable + ''''''')';
I've also made sure single quotes are properly escaped in the #stringvariable.
It's also likely you need to start the query with SET FMTONLY OFF; so I've added that.
Update: To test this I created following simple procedure on a linked server local_server in database TEST_TT
CREATE PROCEDURE [dbo].[tst]
#i VARCHAR(128)
AS
SELECT #i AS field;
I then ran the following:
DECLARE #var VARCHAR(128)='TT.';
SET #var=REPLACE(#var,'''',''''''''''); -- doubly doubled single quotes for the dynamic statement
DECLARE #stmt VARCHAR(4000)='SELECT * INTO ##tt FROM OPENQUERY(local_server,''SET FMTONLY OFF;EXEC TEST_TT.dbo.tst '''''+#var+''''''');';
EXEC (#stmt);
SELECT * FROM ##tt;
DROP TABLE ##tt;
And I received the results. I count 7 (!!) single quotes at the end of the query... yuck! Updated original part with the same number of quotes.

Can not get ##ERROR after EXEC() with Error

Please see the following t-sql code
DECLARE #iError INT
EXEC('select * from sysobj')
SELECT #iError = ##ERROR
PRINT 'Error = ' + CAST(#iError AS VARCHAR(10))
After I run it, it returns error message, which is what I want.
Msg 208, Level 16, State 1, Line 1
Invalid object name 'sysobj'.
Error = 208
However, if I change the query
DECLARE #iError INT
EXEC('select * from sysobjects where ''c'' = 1')
SELECT #iError = ##ERROR
PRINT 'Error = ' + CAST(#iError AS VARCHAR(10))
The output will be
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the varchar value 'c' to data type int.
The problem is any code afer EXEC() is not executed.
In the real stored procedure, I have some code to handle the errors after PRINT. And none of those code executed in second case.
Could someone let me know why this happens?
I tested it on both SQL Server 2008 and 2005.
Thanks
Different errors will have different levels of abort and some of these can be controlled through the use of settings, like ARITHIGNORE and ANSI_WARNINGS.
I suggest reading the following article that explains all of this in great detail.
http://www.sommarskog.se/error-handling-I.html#whathappens
Statement-termination and Batch-abortion
These two groups comprise regular run-time errors, such as duplicates in unique
indexes, running out of disk space etc. As I have already have discussed, which
error that causes which action is not always easy to predict beforehand. This
table lists some common errors, and whether they abort the current
statement or the entire batch.
Look into implementing TRY...CATCH for your error handling. You should be able to put all of your error handling in the CATCH block then.
There's an article on this on msdn here. It has to do with the context in which the EXEC() statement is run. If you include the error trap in the parameter passed to EXEC(), you can stuff it into a temp table and then look at that.
Here's their example:
DECLARE #cmd VARCHAR(1000), #ExecError INT
CREATE TABLE #ErrFile (ExecError INT)
SET #cmd = 'EXEC GetTableCount ' +
'''pubs.dbo.authors''' +
'INSERT #ErrFile VALUES(##ERROR)'
EXEC(#cmd)
SET #ExecError = (SELECT * FROM #ErrFile)
SELECT #ExecError AS '##ERROR'

Error in reading CSV file

I am using the below code in SP, SQL Server 2005
declare #path varchar(500)
set #path = 'E:\Support\test.csv';
print #path
Create table #mytable(
name varchar(max), class varchar(max), roll varchar(max)
)
BULK INSERT #mytable FROM #path
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n'
);
Go
select * from #mytable
drop table #mytable
But it is throwing the following error :
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near '#path'.
Msg 319, Level 15, State 1, Line 9
Incorrect syntax near the keyword 'with'.
If this statement is a common table expression or an xmlnamespaces clause,
the previous statement must be terminated with a semicolon.
Msg 208, Level 16, State 0, Line 1
Invalid object name '#mytable'.
Could anybody help me.
You can't do the following
BULK INSERT #mytable FROM #path
if you are expecting this to translate to
BULK INSERT #mytable FROM 'E:\Support\test.csv'
It's not the file name that's in the varchar, SQL sees it #Path as the data and not a string containing the path.
If you need to use a variable for the path, you will need to use some dynamic SQL which roughly translates to (excuse syntax errors)
DECLARE #SQL varchar(max)
SET #SQL = 'BULK INSERT #mytable FROM '+ #path + '
--Add the rest of your code here
EXEC (#SQL)
If your variable is never going to change though I'd just go ahead and stick the string into the statement itself.
Hope that helps.

Dynamic Function Issue

I am trying to create some dynamic DDL to build a function and when I run it, it keeps giving me an error. I am not sure what I am doing wrong with the format....I have tried a lot of different things and now it is just out of curiousity that I want to understand how to get it to work. Any input is greatly appreciated.
CODE:
DECLARE #SQL nvarchar(max) =
'ALTER FUNCTION dbo.GetFiscalDate()
RETURNS DATETIME
AS
BEGIN
DECLARE #RESULT DATETIME
SELECT #RESULT = #FY
RETURN #RESULT;
END'
,#FY datetime = '01/01/2016'
,#ParamDef nvarchar(50) = N'#FY datetime'
exec sp_executesql #SQL,#ParamDef,#FY
Gives me this error:
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'FUNCTION'.
Msg 178, Level 15, State 1, Line 7
A RETURN statement with a return value cannot be used in this context.
This Code however...works:
DECLARE
#FY nvarchar(10) = '01/01/2015'
,#SQL nvarchar(max)
Select #SQL =
'ALTER FUNCTION dbo.GetFiscalDate()
RETURNS DATETIME
AS
BEGIN
DECLARE #RESULT DATETIME
SELECT #RESULT = ' + #FY + '
RETURN #RESULT;
END'
exec sp_executesql #SQL
What am I missing with this when I want to pass in params instead of concatenating them with the statement?
As usual I greatly appreciate all input.
Thanks,
S
parameters are used in execution plans so that you can reuse the execution plan, not in DDL statements, use your 2nd approach
I don't see where in your string you're including a call to your function.
Whatever sql you put in your string should exec directly in a query window, and altering a function and then listing the params wouldn't do it. You have to exec the function with the params listed in their normal syntax.
Why not pass the #FY variable as a parameter into the function?
I'm not sure what you're trying to do, but I wouldn't expect the approach you've described above to work.