October 11, 2005 at 10:12 am
G'day,
Here is a bit of an interesting situation. Here are three short code examples, nearly identical. This is a cut-and-paste from query analyzer. The situation is a stripped-down example. The first two snippets fail with the error messages as shown. The third snippet works. The only difference between shippet 2 and shippet 3 is that I placed my cursor after [ColName3] ), pressed delete twice and enter once. This leads me to believe that some invisible character is getting into the dynamic string. I am extremely familiar with generating dynamic SQL, with computed columns, and with Unicode. This is the first time I have tried to combine all three. My questions:
Has anyone seen this behavior before? What is the explanation for why is it occurring? What is the solution? My goal is to generate the sql string dynamically. How can I do this and not encounter the errors? On to the code snippets:
drop table WayneTest
DECLARE @SqlCmd VARCHAR(4000),
@Error INT
SET @SqlCmd =
'
CREATE TABLE [WayneTest] (
[ColName1] VARCHAR (10) NOT NULL ,
[ColName2] VARCHAR (20) NOT NULL ,
[ColName3] AS RIGHT(REPLICATE(''X'',30)+ CAST([ColName1] AS NVARCHAR) ,30)
CONSTRAINT [PK_WayneTest] PRIMARY KEY CLUSTERED ( [ColName3] )
 
'
PRINT '<SQLCmd1>' + @SQLCmd + '</SQLCmd1>'
-- EXEC @Error = SP_EXECUTESQL @SQLCmd
EXEC(@SqlCmd)
IF @Error <> 0 SELECT @Error
Server: Msg 8111, Level 16, State 2, Line 2
Cannot define PRIMARY KEY constraint on nullable column in table 'WayneTest'.
Server: Msg 1750, Level 16, State 1, Line 2
Could not create constraint. See previous errors.
DECLARE @SqlCmd NVARCHAR(4000),
@Error INT
SET @SqlCmd =
N'
CREATE TABLE [WayneTest] (
[ColName1] VARCHAR (10) NOT NULL ,
[ColName2] VARCHAR (20) NOT NULL ,
[ColName3] AS RIGHT(REPLICATE(''X'',30)+ CAST([ColName1] AS NVARCHAR) ,30)--
CONSTRAINT [PK_WayneTest] PRIMARY KEY CLUSTERED ( [ColName3] )
 
'
PRINT '<SQLCmd2>' + @SQLCmd + '</SQLCmd2>'
EXEC @Error = SP_EXECUTESQL @SQLCmd
--EXEC(@SqlCmd)
IF @Error <> 0 SELECT @Error
Server: Msg 170, Level 15, State 1, Line 2
Line 2: Incorrect syntax near ')'.
DECLARE @SqlCmd NVARCHAR(4000),
@Error INT
SET @SqlCmd =
N'
CREATE TABLE [WayneTest] (
[ColName1] VARCHAR (10) NOT NULL ,
[ColName2] VARCHAR (20) NOT NULL ,
[ColName3] AS RIGHT(REPLICATE(''X'',30)+ CAST([ColName1] AS NVARCHAR) ,30)--
CONSTRAINT [PK_WayneTest] PRIMARY KEY CLUSTERED ( [ColName3] )
)
'
PRINT '<SQLCmd3>' + @SQLCmd + '</SQLCmd3>'
EXEC @Error = SP_EXECUTESQL @SQLCmd
--EXEC(@SqlCmd)
IF @Error <> 0 SELECT @Error
query batch completed
October 11, 2005 at 11:11 am
When writing Dynamic SQL you have two choices to avoid those problems:
1) Do not break the string into several lines
2) If you must break it use explicit CRLF Terminator at each line end
Cheers,
Noel
* Noel
October 11, 2005 at 12:51 pm
Thanks Noel,
Your advice got me moving in the right direction. I was concatenating three NVARCHAR strings to create the complete command. I converted the code generator to use a single nvarchar string all the way through. That resolved the first issue completely.
The second issue still exists, but I have a feasible workaround.
Even though the base columns are "NOT NULL", the computed column thinks that it is nullable. As such, I am not permitted to create a primary key constraint on the computed column. However, I am able to create a unique constraint. Since the base column is "not null", this provides the net effect of a primary key. Seems like this is a bug in the SQL server parser/analyzer. If ColumnA is "not null", then 'X' + ColumnA must also be "not null".
Thanks for the suggestion. It helped break my mental block.
Have a good day
Wayne
October 11, 2005 at 2:35 pm
Correct!
I was just refering to the syntax error issue. Good point to keep in mind about the NOT NULL, You can overcome the issue by using ISNULL function
DECLARE @SqlCmd NVARCHAR(4000),
@Error INT
SET @SqlCmd =
N'
CREATE TABLE [WayneTest] (
[ColName1] VARCHAR (10) NOT NULL ,
[ColName2] VARCHAR (20) NOT NULL ,
[ColName3] AS ISNULL(RIGHT(REPLICATE(''X'',30)+ CAST([ColName1] AS NVARCHAR) ,30),''XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX''),
CONSTRAINT [PK_WayneTest] PRIMARY KEY CLUSTERED ( [ColName3] )
)'
--
PRINT '<SQLCmd3>' + @SQLCmd + '</SQLCmd3>'
--EXEC @Error = SP_EXECUTESQL @SQLCmd
EXEC(@SqlCmd)
IF @@Error <> 0 SELECT @Error
-- DROP TAble [WayneTest]
Not Pretty but it works!
* Noel
Viewing 4 posts - 1 through 3 (of 3 total)
You must be logged in to reply to this topic. Login to reply