18

I am trying to write a stored procedure to assist with development of our database, but I am having some trouble using it. For example:

DECLARE @pID int;
SET @pID = 1;
EXEC WriteLog 'Component', 'Source', 'Could not find given id: ' + CAST(@pID AS varchar);

This yields the error (on SQL Server 2005):

Msg 102, Level 15, State 1, Line 4 Incorrect syntax near '+'.

Can someone explain to me why my syntax is incorrect, and the right way to solve this problem?

live-love
  • 48,840
  • 22
  • 240
  • 204
WorkerThread
  • 2,195
  • 2
  • 19
  • 23

7 Answers7

19

You need to use an intermediate variable. SQL Server does not support this kind of operation in the parameter list itself though it has been on the TODO list for a few years! (See Connect Item: Use scalar functions as stored procedure parameters)

The grammar for EXEC is

[ { EXEC | EXECUTE } ]
    { 
      [ @return_status = ]
      { module_name [ ;number ] | @module_name_var } 
        [ [ @parameter = ] { value 
                           | @variable [ OUTPUT ] 
                           | [ DEFAULT ] 
                           }
        ]
      [ ,...n ]
      [ WITH <execute_option> [ ,...n ] ]
    }
[;]

The documentation is not currently that clear on an acceptable format for value but it seems to be only "simple" expressions such as literal values or @@ prefixed system functions (such as @@IDENTITY). Other system functions such as SCOPE_IDENTITY() are not permitted (even those which do not require parentheses such as CURRENT_TIMESTAMP are not allowed).

So for the time being you need to use syntax such as the below

DECLARE @pID INT;

SET @pID = 1;

/*If 2008+ for previous versions this needs to be two separate statements*/
DECLARE @string VARCHAR(50) = 'Could not find given id: ' + CAST(@pID AS VARCHAR(11))

EXEC WriteLog
  'Component',
  'Source',
  @string 
Martin Smith
  • 438,706
  • 87
  • 741
  • 845
  • 4
    I was hoping to avoid intermediate variables. Is there a proper way to do this without introducing them? – WorkerThread Feb 08 '11 at 17:30
  • Ah, just saw your explanation. Thank you for clarifying this. – WorkerThread Feb 08 '11 at 17:31
  • @Worker - It's all a bit annoying. MS acknowledge as much here https://connect.microsoft.com/SQLServer/feedback/details/352110/t-sql-use-scalar-functions-as-stored-procedure-parameters – Martin Smith Feb 08 '11 at 17:33
  • I fixed a probably accidental misplacement of `'Source'` but I must add that the syntax `declare @var type = value` is only supported since SQL Server 2008 (and the question is tagged `sql-server-2005`). – Andriy M Aug 19 '12 at 13:55
  • @AndriyM - Thanks. Absolutely correct but I decided to leave it "as is" with an explanatory comment despite the tag as the proportion of people on older versions that cannot use the combined syntax will continue to fall. – Martin Smith May 12 '13 at 14:07
2
DECLARE @pID int;
declare @IdAsString varchar(100)

SET @pID = 1;

Select @IdAsString ='Could not find given id: ' + Cast(@pId as varchar(10))

EXEC WriteLog 'Component', 'Source', @IdAsString

As pointed out by Martin, the following only applies to columns not variables.

Note that I have amended your cast to varchar(10) this will allow for integers larger than 1 digit. varchar will only allow 1 character

codingbadger
  • 42,678
  • 13
  • 95
  • 110
  • 1
    @Barry - That is true for a column but the default for a `varchar` variable is 10. `select CAST('1234567890' as varchar)`. You need `11` though for the full range of `int` if you are going to allow for negatives. – Martin Smith Feb 08 '11 at 17:34
  • @Martin - well I did not know that. Thanks for pointing out. Do you know why the behaviour differs? – codingbadger Feb 08 '11 at 17:47
  • @Barry - No - it seems quite a baffling inconsistency. I guess there's probably some historic reason... – Martin Smith Feb 08 '11 at 17:49
  • I appreciate your additional note, thanks for helping me understand SQL Server a little better! – WorkerThread Feb 08 '11 at 18:14
  • @Martin: The default length for varchar depends on the situation. `When n is not specified in a data definition or variable declaration statement, the default length is 1. When n is not specified when using the CAST and CONVERT functions, the default length is 30.`. (Taken from http://msdn.microsoft.com/en-us/library/ms176089.aspx) This is also true for SQL Server 2000 in particular, and I wonder if they are going to get rid of this 'inconsistency' soon enough. – Andriy M Feb 09 '11 at 15:59
  • @Andriy - Ah right I thought it was 10 but was only going off memory - thanks for the correction! – Martin Smith Feb 09 '11 at 16:08
1

You can't do operations on the parameters of a stored procedure. You should assign that value on another variable and then pass it to your SP.

DECLARE @pID int, @nameId VARCHAR(100);
SET @pID = 1;
SET @nameId = 'Could not find given id: ' + CAST(@pID AS varchar);

EXEC WriteLog 'Component', 'Source', @nameId
Lamak
  • 69,480
  • 12
  • 108
  • 116
1

Use this code to print a Sql Server Error message:

BEGIN TRY  
    -- Generate a divide-by-zero error.  
    SELECT 1/0;  
END TRY  
BEGIN CATCH  
    SELECT  
        ERROR_NUMBER() AS ErrorNumber  
        ,ERROR_SEVERITY() AS ErrorSeverity  
        ,ERROR_STATE() AS ErrorState  
        ,ERROR_PROCEDURE() AS ErrorProcedure  
        ,ERROR_LINE() AS ErrorLine  
        ,ERROR_MESSAGE() AS ErrorMessage;  
END CATCH;  
GO  

Here is the result set.

Copy
-----------

(0 row(s) affected)

ErrorNumber ErrorSeverity ErrorState  ErrorProcedure  ErrorLine  ErrorMessage
----------- ------------- ----------- --------------- ---------- ----------------------------------
8134        16            1           NULL            4          Divide by zero error encountered.

(1 row(s) affected)
live-love
  • 48,840
  • 22
  • 240
  • 204
0

DECLARE @id int

SET @id = 10

SELECT LTRIM(RTRIM(STR(@id))) AS stringValue

0

Perhaps something like this?

DECLARE @pID int;
SET @pID = 1;

DECLARE @Message NVARCHAR(50);

SET @Message = 'Could not find given id: ' + CAST(@pID AS varchar)
EXEC WriteLog 'Component', 'Source', @Message;
Bruno Costa
  • 2,708
  • 2
  • 17
  • 25
0

Try this instead...

DECLARE @pID int;
SET @pID = 1;

DECLARE @message varchar(255);
SET @message = 'Could not find given id: ' + CAST(@pID AS varchar)

EXEC WriteLog 'Component', 'Source', @message;
Craig T
  • 1,031
  • 1
  • 7
  • 13