Quoted_Identifier SQL Server - Off - Unsure How - sql-server

We've been having an issue every few months where all of a sudden a job or procedure will start failing due to a quoted_Identifier issue. The quoted identifier in the proc or even table will change from 1 to 0 and we don't see any recent modified date on that record. We aren't sure how this is happening and because it's so sporadic, I can't reproduce it or trace it easily. Any ideas as to why this is occurring or what I can do to find out. I've done a lot of research without luck so far.
Thanks

You could create a DDL trigger activated by CREATE/ALTER PROCEDURE events. Inside this trigger you could use EVENTDATE function to get information about SQL statements execute including ANSI_NULLS and QUOTED_IDENTIFIER settings.
For example, you could use ddlDatabaseTriggerLog ddl trigger from Adventure Works OLTP database that insert into [dbo].[DatabaseLog] all ddl changes from current database.
DDL Trigger:
CREATE TRIGGER [ddlDatabaseTriggerLog] ON DATABASE
FOR DDL_DATABASE_LEVEL_EVENTS AS
BEGIN
SET NOCOUNT ON;
SET ANSI_WARNINGS ON;
DECLARE #data XML;
DECLARE #schema sysname;
DECLARE #object sysname;
DECLARE #eventType sysname;
SET #data = EVENTDATA();
SET #eventType = #data.value('(/EVENT_INSTANCE/EventType)[1]', 'sysname');
SET #schema = #data.value('(/EVENT_INSTANCE/SchemaName)[1]', 'sysname');
SET #object = #data.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname')
IF #object IS NOT NULL
PRINT ' ' + #eventType + ' - ' + #schema + '.' + #object;
ELSE
PRINT ' ' + #eventType + ' - ' + #schema;
IF #eventType IS NULL
PRINT CONVERT(nvarchar(max), #data);
INSERT [dbo].[DatabaseLog]
(
[PostTime],
[DatabaseUser],
[Event],
[Schema],
[Object],
[TSQL],
[XmlEvent]
)
VALUES
(
GETDATE(),
CONVERT(sysname, CURRENT_USER),
#eventType,
CONVERT(sysname, #schema),
CONVERT(sysname, #object),
#data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(max)'),
#data
);
END;
GO
[dbo].[DatabaseLog]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[DatabaseLog](
[DatabaseLogID] [int] IDENTITY(1,1) NOT NULL,
[PostTime] [datetime] NOT NULL,
[DatabaseUser] [sysname] NOT NULL,
[Event] [sysname] NOT NULL,
[Schema] [sysname] NULL,
[Object] [sysname] NULL,
[TSQL] [nvarchar](max) NOT NULL,
[XmlEvent] [xml] NOT NULL,
CONSTRAINT [PK_DatabaseLog_DatabaseLogID] PRIMARY KEY NONCLUSTERED
(
[DatabaseLogID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
Who/when changed dbo.uspGetEmployeeManagers procedure ?
SELECT *
FROM [dbo].[DatabaseLog] x
WHERE x.[Event] IN ('CREATE_PROCEDURE', 'ALTER_PROCEDURE')
AND x.[Schema] = 'dbo'
AND x.[Object] = 'uspGetEmployeeManagers'
XmlEvent column content:
<EVENT_INSTANCE>
<EventType>CREATE_PROCEDURE</EventType>
...
<TSQLCommand>
<SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE" />
<CommandText>
CREATE PROCEDURE [dbo].[uspGetEmployeeManagers]
#BusinessEntityID [int]
AS
...

Those scripts are helpful and I'll use them in the future. I figured out what the issue is. A stored procedure had quoted_identifier set to 0 and it had been that way for at least a year. However, someone created a filtered index on a table that the stored procedure was using. They didn't realize that the filtered index required quoted_identifier to be set to 1.

Related

SQL Server delete all tables under special schema with temporal tables

I'm trying to delete a database scheme with temporal tables.
Non of the existing scripts found through googling, supports temporal tables.
Is there anyone already done this?
There are many temporal tables on that scheme with many constraints with dependencies. so when I try to drop the scheme it complain about dependencies.
Basically I'm looking for a stored procedure or something that go through all the DB objects and remove one by one.
Script to Create sample tables
USE [master];
GO
CREATE DATABASE [TestDb];
GO
USE [TestDb];
GO
CREATE SCHEMA [TestScheme];
GO
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
CREATE TABLE [TestScheme].[Country]
(
[CountryCode] [char](2) NOT NULL,
[Country] [varchar](60) NOT NULL,
[ValidFrom] [datetime2](2) GENERATED ALWAYS AS ROW START NOT NULL,
[ValidTo] [datetime2](2) GENERATED ALWAYS AS ROW END NOT NULL,
CONSTRAINT [PK_TestScheme_Country_CountryCode]
PRIMARY KEY CLUSTERED([CountryCode] ASC)
WITH (PAD_INDEX = ON, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 95) ON [PRIMARY],
PERIOD FOR SYSTEM_TIME([ValidFrom], [ValidTo])
) ON [PRIMARY]
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [TestScheme].[CountryHistory]));
GO
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
CREATE TABLE [TestScheme].[Address]
(
[AddressId] [int] IDENTITY(1, 1) NOT NULL,
[City] [varchar](100) NOT NULL,
[CountryCode] [char](2) NOT NULL,
[ValidFrom] [datetime2](7) GENERATED ALWAYS AS ROW START NOT NULL,
[ValidTo] [datetime2](7) GENERATED ALWAYS AS ROW END NOT NULL,
CONSTRAINT [PK_TestScheme_Address_AddressId]
PRIMARY KEY CLUSTERED([AddressId] ASC)
WITH (PAD_INDEX = ON, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY],
PERIOD FOR SYSTEM_TIME([ValidFrom], [ValidTo])
)
ON [PRIMARY]
WITH (SYSTEM_VERSIONING = ON(HISTORY_TABLE = [TestScheme].[AddressHistory]));
GO
ALTER TABLE [TestScheme].[Address] WITH CHECK
ADD CONSTRAINT [FK_TestScheme_CountryCode]
FOREIGN KEY([CountryCode]) REFERENCES [TestScheme].[Country]([CountryCode]);
GO
ALTER TABLE [TestScheme].[Address] CHECK CONSTRAINT [FK_TestScheme_CountryCode];
GO
Query to drop scheme:
USE [TestDb];
GO
DROP SCHEMA [TestScheme];
GO
Query to delete table:
USE [TestDb]
GO
ALTER TABLE [TestScheme].[Country] SET (SYSTEM_VERSIONING = OFF)
GO
IF EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[TestScheme].[Country]') AND type in (N'U'))
DROP TABLE [TestScheme].[Country]
GO
IF EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[TestScheme].[CountryHistory]') AND type in (N'U'))
DROP TABLE [TestScheme].[CountryHistory]
GO
So the problem is there are many DB objects that I really don't want to create a huge script to delete one by one.
Thanks!
Thanks every one, following is the script I created and it worked for me.
USE TestDb;
GO
DECLARE #SchemeName varchar(50)= 'TestScheme';
DECLARE #DatabaseName varchar(50)= 'TestDb';
DECLARE #sql nvarchar(max)= '';
/*Removing versioning on temporal tables*/
WITH selectedTables
AS (SELECT concat('[', #DatabaseName, '].[', #SchemeName, '].[', name, ']') AS TableName
FROM SYS.TABLES WHERE history_table_id IS NOT NULL AND SCHEMA_NAME(schema_id) = #SchemeName)
SELECT #sql = COALESCE(#sql, N'') + 'ALTER TABLE ' + TableName + ' SET ( SYSTEM_VERSIONING = OFF );'
FROM selectedTables;
SELECT #sql;
EXEC sp_executesql #sql;
/*Remove constraints*/
SET #sql = N'';
SELECT #sql = COALESCE(#sql, N'') + N'ALTER TABLE ' + QUOTENAME(s.name) + N'.' + QUOTENAME(t.name) + N' DROP CONSTRAINT ' + QUOTENAME(c.name) + ';'
FROM SYS.OBJECTS AS c INNER JOIN SYS.TABLES AS t ON c.parent_object_id = t.[object_id]
INNER JOIN SYS.SCHEMAS AS s ON t.[schema_id] = s.[schema_id]
WHERE c.[type] IN( 'D', 'C', 'F', 'PK', 'UQ' ) AND s.name = #SchemeName
ORDER BY c.[type];
SELECT #sql;
EXEC sp_executesql #sql;
/*Delete Tables*/
SET #sql = N'';
SELECT #sql = COALESCE(#sql, N'') + N'DROP TABLE ['+#SchemeName+'].' + QUOTENAME(TABLE_NAME) + N';' + CHAR(13)
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = #SchemeName AND TABLE_TYPE = 'BASE TABLE';
SELECT #sql
EXEC sp_executesql #sql;
/*Drop scheme*/
SET #sql = N'';
SELECT #sql = COALESCE(#sql, N'') + N'DROP SCHEMA IF EXISTS ' + #SchemeName + ';' + CHAR(13);
SELECT #sql
EXEC sp_executesql #sql;
GO
Thanks again!

Sending email using sp_send_dbmail() does not work sometimes

I am sending notification email using SQL Server but sometimes emails aren't sent to users.
Here is my SQL table that I store emails which it will be sent to users
CREATE TABLE [dbo].[EmailNotification](
[Id] [INT] IDENTITY(1,1) NOT NULL,
[EmailAdress] [NVARCHAR](50) NULL,
[EmailBody] [NVARCHAR](500) NULL,
[EmailSubject] [NVARCHAR](250) NULL,
[Attachment] [NVARCHAR](500) NULL,
[EmailSent] [BIT] NULL CONSTRAINT [DF_EmailNotification_EmailSent] DEFAULT
((0)),
[EmailCreateDate] [DATETIME] NULL CONSTRAINT
[DF_EmailNotification_EmailCreateDate] DEFAULT (GETDATE()),
[EmailSentDate] [DATETIME] NULL,
CONSTRAINT [PK_EmailNotification] PRIMARY KEY CLUSTERED
([Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
And I have created a job which executes this procedure every 1 minute
CREATE PROCEDURE [dbo].[spSendEmail]
AS
BEGIN
BEGIN TRAN
DECLARE #id BIGINT
DECLARE #max_id BIGINT
DECLARE #query NVARCHAR(1000)
DECLARE #EmailBody NVARCHAR(1000)
DECLARE #EmailAdress NVARCHAR(500)
DECLARE #EmailSubject NVARCHAR(500)
DECLARE #attachments NVARCHAR(1000)
if exists (SELECT * FROM dbo.EmailNotification where EmailSent=0)
begin
SELECT #id=MIN(id) FROM dbo.EmailNotification where EmailSent=0
SELECT #EmailAdress=EmailAdress,#EmailBody=EmailBody,#EmailSubject=EmailSubject,#attachments=Attachment
FROM EmailNotification WHERE id = #id
exec [msdb].[dbo].[sp_send_dbmail] #profile_name='Notification',
#recipients=#EmailAdress,
#blind_copy_recipients='example.email.com',
#subject=#EmailSubject,
#body=#EmailBody,
#file_attachments=#attachments
end
IF(##ERROR>0)
BEGIN
ROLLBACK
END
ELSE
BEGIN
UPDATE EmailNotification set EmailSent=1, EmailSentDate=getdate() WHERE Id=#id
COMMIT
END
What do you mean : spSendEmail is not triggering sp_send_dbmail? sp_send_dbmail is triggered but doesn't do anything....?
Please get the return code of sp_send_dbmail :
0 => OK
<> 0 => Error occured
DECLARE #result int;
DECLARE #ErrorNb int;
EXECUTE #result = exec [msdb].[dbo].[sp_send_dbmail] #profile_name='EDMS email notification',
#recipients=#EmailAdress,
#blind_copy_recipients='example.email.com',
#subject=#EmailSubject,
#body=#EmailBody,
#file_attachments=#attachments
SET #ErrorNb = ##ERROR
IF #result <> 0
BEGIN
-- Something goes wrong
SELECT #result,#ErrorNb
END
You can also use TRY :
BEGIN TRY
EXECUTE exec [msdb].[dbo].[sp_send_dbmail] #profile_name='EDMS email notification',
#recipients=#EmailAdress,
#blind_copy_recipients='example.email.com',
#subject=#EmailSubject,
#body=#EmailBody,
#file_attachments=#attachments
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE();
END CATCH

BULK Insert Fails with different files sizes

I have this problem where bulk insert fails with different files sizes, specifically, the first file would contain 433 rows while the second file has 2 rows only. But when I insert the 2 rowed file by itself, there's no error.
I have this as my bulk insert statement
set #sql = 'BULK INSERT #temptable
FROM '''+#location+'''
WITH
(
FIELDTERMINATOR = '','',
ROWTERMINATOR = ''\n'',
MAXERRORS = 100,
TABLOCK,
FIRSTROW = 2
)'
The above statement is contained in a stored procedure.
For more information, I will put my stored procedure here.
USE [THERMOWAVE]
GO
/****** Object: StoredProcedure [dbo].[UploadOmronData] Script Date: 02/13/2017 13:48:54 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[UploadOmronData]
#location as nvarchar(max)
as
begin
declare #sql as nvarchar(max)
-- give #location data from VB.net
--declare #location as varchar(max)
--set #location = 'C:\Users\jsumgo\Documents\Visual Studio 2010\Projects\TestUploader\TestUploader\bin\Debug\12320161428420dataUpload.csv'
-- Joshua Magsino 11/28/2016
-- TSql to upload dynamic column data source
--before uploading, make sure that datasource table columns are named equal to database table column
--Check if data is to be stored as reference or could be destroyed
--Check database to store and columns that would be affected
--set configurations to enable Ad Hoc Distributed Queries
/*
sp_configure 'show advanced options', 1;
RECONFIGURE;
GO
sp_configure 'Ad Hoc Distributed Queries', 1;
RECONFIGURE;
GO
*/
-- configure SQL to execute Ad Hoc Queries using MSOFFICE 2010
/*
USE [master]
GO
EXEC master.dbo.sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0', N'AllowInProcess', 1
GO
EXEC master.dbo.sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0', N'DynamicParameters', 1
GO
*/
-- fill temptable with data
---------------------------------------------------------------------------------------------------------------
--drop table #temptable
--create blank temptable
create table #temptable
(
[Number] Varchar(20)
)
--declare #sql as varchar(max)
declare #cursor CURSOR
declare #colname as nvarchar(30)
SET #cursor = CURSOR FOR
(Select colname from dbo.sorting)
OPEN #cursor
FETCH NEXT
FROM #cursor INTO #colname
WHILE ##FETCH_STATUS = 0
BEGIN
-- add from column 2 to end
if #colname <> 'Number'
begin
set #sql = 'ALTER TABLE #temptable ADD ['+#colName+'] NVARCHAR(max) NULL'
EXEC sp_executesql #sql, N'#colname nvarchar(max)', #colname
end
FETCH NEXT
FROM #cursor INTO #colName
END
CLOSE #cursor
DEALLOCATE #cursor
---------------------------------------------------------------------------------------------------------------
--declare #location as varchar(max)
--set #location = 'D:\Omron Data\Data\sample\asdasdasdasdasd - Copy.csv'
--declare #sql as varchar(max)
--Insert Data from CSV file to Temptable
set #sql = 'BULK INSERT #temptable
FROM '''+#location+'''
WITH
(
FIELDTERMINATOR = '','',
ROWTERMINATOR = ''\n'',
MAXERRORS = 100,
TABLOCK,
FIRSTROW = 2
)'
EXEC sp_executesql #sql, N'#location as nvarchar(max)', #location
--Insert Statement
--If the location of the new column is in the last column of the CSV file, then direct bulk insert
--safe solution is to insert based on the column name of each table
--cursor is needed
DECLARE #DBcursor CURSOR
DECLARE #DBColname as varchar(30)
DECLARE #DBCOL as nvarchar(max)
--Get Table Names from dbo.sorting
--since all table names are inserted from dbo.sorting, get column names from dbo.sorting
SET #DBcursor = CURSOR FOR
(Select colname from dbo.sorting)
OPEN #DBcursor
FETCH NEXT
FROM #DBcursor INTO #DBColname
WHILE ##FETCH_STATUS = 0
BEGIN
--assemble columns
set #DBCOL = (isnull(#DBCOL,''))+'['+ #DBColname +'],'
FETCH NEXT
FROM #DBcursor INTO #DBColname
END
CLOSE #DBcursor
DEALLOCATE #DBcursor
--remove last (,) from columns
set #DBCOL =LEFT(#DBCOL, LEN(#DBCOL) - 1)
--insert data from temptable to DataUpload
set #sql = 'insert into DataToUpload ('+#DBCOL+') select '+#DBCOL+' from #tempTable'
EXEC sp_executesql #sql,N'#DBCOL NVARCHAR(max)', #DBCOL
--Put BatchID for DataUpload
--BatchId format,Batch + Number(000) + year + month + day
declare #number as nvarchar(max)
set #number = RIGHT('000' +CAST((select ISNULL(max(case when BatchID = null or BatchID = '' then '000' else right(SUBSTRING(BatchID,1,8),3)+ 1 end),'000') from DataToUpload)AS VARCHAR(3)),3)
set #sql = 'update DataToUpload set BatchID = ''Batch'+cast(#number as varchar(max))+cast(year(getdate()) as varchar(4))+''+cast(MONTH(getdate())as varchar(2))+''+cast(DAY(getdate())as varchar(2)) +''' where BatchID is null'
EXEC sp_executesql #sql,N'#number NVARCHAR(max)', #number
--select * from DataToUpload order by BAtchID,Number asc
--select * from dbo.Sorting
--select * from temptable
--delete from DataToUpload
--clear dbo.sorting
delete from dbo.Sorting
--remove temptable
drop table #temptable
DBCC FREEPROCCACHE WITH NO_INFOMSGS;
end
and then the command in a vb.net system that fires the stored procedure through here.
Sub UploadOmronData(ByVal location As String)
'SQL Stored Procedure -- Save data from CSV file to SQL
Dim sqlcom As New SqlClient.SqlCommand
Try
With sqlcom
conn.Open()
.Connection = conn
.CommandTimeout = 100
.CommandText = "dbo.UploadOmronData"
.CommandType = CommandType.StoredProcedure
.Parameters.AddWithValue("#location", location)
.ExecuteReader()
End With
Catch ex As Exception
MsgBox(ex.Message + " " + location)
GC.Collect()
sqlcom.Dispose()
frmMain.Close()
End Try
conn.Close()
sqlcom.Dispose()
GC.Collect()
End Sub
And the error message which I receive:
Bulk load data conversion error (truncation) for row 2, column 1 (Number).
Bulk load data conversion error (truncation) for row 3, column 1 (Number).
ADDED INFORMATION
Here is the table structure of dbo.DataToUpload
CREATE TABLE [dbo].[DataToUpload](
[Number] [int] NULL,
[Date&Time] [nvarchar](max) NULL,
[ms] [nvarchar](50) NULL,
[CH34] [nvarchar](50) NULL,
[CH35] [nvarchar](50) NULL,
[CH36] [nvarchar](50) NULL,
[CH37] [nvarchar](50) NULL,
[CH38] [nvarchar](50) NULL,
[CH39] [nvarchar](50) NULL,
[Alarm1-10] [nvarchar](50) NULL,
[Alarm11-20] [nvarchar](50) NULL,
[Alarm21-30] [nvarchar](50) NULL,
[Alarm31-40] [nvarchar](50) NULL,
[AlarmOut] [nvarchar](50) NULL,
[BatchID] [nvarchar](50) NULL,
[CH31] [nvarchar](20) NULL,
[CH32] [nvarchar](20) NULL,
[CH33] [nvarchar](20) NULL
) ON [PRIMARY]
and the rows that I'm trying to insert
Number,Date&Time,ms,CH34,CH35,CH36,CH37,CH38,CH39,Alarm1-10,Alarm11-20,Alarm21-30,Alarm31-40,AlarmOut
1,2016-08-08 16:23:16,000,+61.2,+64.0,+35.4,+94.4,+185.4,+151.2,LLLLLLLLLL,LLLLLLLLLL,LLLLLLLLLL,LLLLLLLLLL,LLLL
2,2016-08-08 16:23:26,000,+61.1,+64.4,+35.4,+94.3,+185.4,+151.2,LLLLLLLLLL,LLLLLLLLLL,LLLLLLLLLL,LLLLLLLLLL,LLLL
and If it mayhelp, the system I created is a background worker, since I have to run the code always.
I reckon the cause is that you're asking BULK INSERT to load 14 columns of data, but you're importing into #TempTable which doesn't have enough fields in it.
Your code creates a #tempTable table, and you use a CURSOR to add extra fields to it... but I reckon the end result isn't a table with 14 fields in it.
Before your BULK INSERT #temptable command gets run, how many fields are in the #temptable table ?
For example, if you just had one field in this table, when you ran the bulk-insert it would insist on trying to import the entire row into that one field, complete with all the commas, but, of course, it doesn't fit in a 20-character string.
CREATE TABLE #temptable
(
[Number] VARCHAR(20)
)
The solution... simply change your temporary table to have the correct number of columns, and the BULK INSERT will work fine:
CREATE TABLE #temptable
(
[Number] NVARCHAR(200),
[Datey] datetime,
[ms] NVARCHAR(200),
[CH34] NVARCHAR(200),
[CH35] NVARCHAR(200),
[CH36] NVARCHAR(200),
[CH37] NVARCHAR(200),
[CH38] NVARCHAR(200),
[CH39] NVARCHAR(200),
[Alarm110] NVARCHAR(200),
[Alarm1120] NVARCHAR(200),
[Alarm2130] NVARCHAR(200),
[Alarm3140] NVARCHAR(200),
[AlarmOut] NVARCHAR(200)
)
Good luck !
P.S. One piece of the puzzle which is missing.... What data do you have in your dbo.sorting table ? This will dictate which fields end up in your temporary table, but you don't explain how this table is populated, or what data it contains.
The attributes
[BatchID] [nvarchar](50) NULL,
[CH31] [nvarchar](20) NULL,
[CH32] [nvarchar](20) NULL,
[CH33] [nvarchar](20) NULL
are missing from your file. With BULK_INSERT the columns have to match perfectly. Fix the number of columns, and it should fix the error.

SQL Server : create table using variables

When trying to execute the following, I get the errors
Msg 102, Level 15, State 1, Line 9
Incorrect syntax near 'GO'.
Msg 102, Level 15, State 1, Line 11
Incorrect syntax near 'GO'.
Msg 102, Level 15, State 1, Line 13
Incorrect syntax near 'GO'.
Can someone tell me where I am going wrong? I don't understand how the syntax is wrong
DECLARE #table nvarchar(100);
DECLARE #sql nvarchar(max);
SET #table = 'FooTable';
SET #sql = N'CREATE TABLE [dbo].[' + #table + '](
[id] [int] IDENTITY(1,1) NOT NULL,
[AddedBy] [int] NOT NULL,
[AddedDate] [datetime2](7) NOT NULL,
CONSTRAINT [PK_' + #table + '] PRIMARY KEY CLUSTERED
( [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[' + #table + '] ADD CONSTRAINT [DF_' + #table + '_AddedBy] DEFAULT ((-1)) FOR [AddedBy]
GO
ALTER TABLE [dbo].[' + #table + '] ADD CONSTRAINT [DF_' + #table + '_AddedDate] DEFAULT (getutcdate()) FOR [AddedDate]
GO';
exec (#sql)
Thanks for your assistance.
SQL server is not happy about sending batches in a dynamic context using exec(). So forget about GO. Just slice up your query where GO should be and exec() slices one by one:
DECLARE #table nvarchar(100);
DECLARE #sql nvarchar(max);
SET #table = 'FooTable';
SET #sql = N'CREATE TABLE [dbo].[' + #table + '](
[id] [int] IDENTITY(1,1) NOT NULL,
[AddedBy] [int] NOT NULL,
[AddedDate] [datetime2](7) NOT NULL,
CONSTRAINT [PK_' + #table + '] PRIMARY KEY CLUSTERED
( [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]'
exec (#sql)
SET #sql = 'ALTER TABLE [dbo].[' + #table + '] ADD CONSTRAINT [DF_' + #table + '_AddedBy] DEFAULT ((-1)) FOR [AddedBy]'
exec (#sql)
SET #sql = 'ALTER TABLE [dbo].[' + #table + '] ADD CONSTRAINT [DF_' + #table + '_AddedDate] DEFAULT (getutcdate()) FOR [AddedDate]'
exec (#sql)
The syntax would be fine if you executed the code inside the management tool which understands the GO command as a batch separator (just like the isql and osql tools). When you execute the code using exec() the GO command is not understood, which is why you get the error.
The solution is to either remove the GO statements (or replace them with ; which ends a statement), and it will execute fine, or inline the constraints and skip the alter table statements altogether (which looks cleaner in my opinion):
SET #sql =
N'CREATE TABLE [dbo].[' + #table + '](
[id] int IDENTITY(1,1) NOT NULL,
[AddedBy] int NOT NULL CONSTRAINT [DF_' + #table + '_AddedBy] DEFAULT ((-1)),
[AddedDate] datetime2(7) NOT NULL CONSTRAINT [DF_' + #table + '_AddedDate] DEFAULT (getutcdate()) ,
CONSTRAINT [PK_' + #table + '] PRIMARY KEY CLUSTERED ( [id] ASC )
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY]
';
Also, there is really no need to use quoted identifiers with the types (or even the column names), so you might as well remove the brackets [].

TSQL sp_executesql

I have a simple table:
CREATE TABLE [dbo].[test]
(
[eins] [varchar](50) NOT NULL,
[zwei] [varchar](50) NULL,
CONSTRAINT [PK_test]
PRIMARY KEY CLUSTERED ([eins] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
with two columns eins und zwei, both varchar(50)
with the values
insert into test(eins, zwei) values(1,2)
1 and 2 in the corresponding columns.
The query
select eins from test
gives the correct result of 1
the following code also gives the correct result of 1 in the results window:
declare
#in varchar(50),
#sql nvarchar(500)
set #in = 'eins'
set #sql = 'select ' + #in + ' from test'
Exec(#sql)
However, it doesn't make use of an output parameter and I need the result for further processing.
So, I try:
exec sp_executesql N' Select #1 from test where zwei = #2',N'#1 nvarchar(100),#2 nvarchar(100)',#1=N'eins',#2=N'2'
with an expected result of 1. However: the result is eins, i.e., the column name, not the value.
How can I query for something like Select #Variable from #Variable2 where #variabel3 = #Variable4?
The table and columns can be non-variable, if need be, what's primarily important is, the Select #Variable. I need this value for further processing.
Try something like this
DECLARE #result int
exec sp_executesql
N'Select #1=eins from test where zwei = #2',
N'#1 nvarchar(100) OUTPUT,#2 nvarchar(100)',
#1=#result OUTPUT,#2=N'2'
SELECT #result
What that does is say that the #1 is an OUTPUT variable inside the EXECed query string. Then it binds #result to the #1, so you can retrieve it. I've never found OUTPUT parameters very intuitive to use.
The Code from DWright in the last post has the correct result, but the main problem isn't solved.
I dont know the name of the column while writing the code. The following code seems to be correct:
Declare #result int
Declare #sql nvarchar(500)
Declare #columnname nvarchar(50)
set #columnname = 'eins'
set #sql= N'Select #1= ' + #columnname +' from test1 where zwei = #2'
exec sp_executesql
#sql,
N'#1 nvarchar(100) OUTPUT,#2 nvarchar(100)',
#1=#result OUTPUT,#2=N'2'
SELECT #result
And the result is the expectet 1
Thank you for helping

Resources