Setting SQL Server compatibility level based on the server in script - sql-server

When I try to set the compatibility level for SQL Server in a script it errors out for SQL Server 2008. I want this script to be same to executed against all the servers - 2008, 2012 or 2014 which we currently support.
-- Set database compatibility --
IF SUBSTRING(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR),1 ,2) >= 11
BEGIN
RAISERROR ('sql server 12 and above', 10, 1)
ALTER DATABASE JJAI_TESTDB SET COMPATIBILITY_LEVEL = 110
END
ELSE
BEGIN
RAISERROR ('sql server 2008',10, 1)
ALTER DATABASE JJAI_TESTDB SET COMPATIBILITY_LEVEL = 100
END
GO
Below is the error:
Msg 15048, Level 16, State 1, Line 5
Valid values of the database compatibility level are 80, 90, or 100.

Okay, I was able to do it by executing the alter statement within an execute statement like below.
/* Set database compatibility */
IF SUBSTRING(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR),1 ,2) >= 11
EXECUTE ('ALTER DATABASE $(DATABASENAME) SET COMPATIBILITY_LEVEL = 110')
ELSE
EXECUTE ('ALTER DATABASE $(DATABASENAME) SET COMPATIBILITY_LEVEL = 100')
GO

Related

Data Entry gives 42000 sqlstate after SQL Server database migration

Brief synopsis: a SQL Server database was migrated from SQL Server 2012 on Windows Server 2012 R2 STD to SQL Server 2017 on Windows Server 2016 STD. Still running in 110 compatibility mode and no SQL Server changes.
The application was repointed and using ODBC to connect. The following error is seen whenever a user attempts data entry/changes via the application. I have attached the stored procedure code which caused the error. The table definition in SSMS shows an id column NOT NULL so nothing wrong with the DDL. I have run sp_blitz and it highlighted 'Objects created with dangerous SET Options' for the offending database. The sp_blitz URL takes me to https://www.brentozar.com/go/badset which highlights incorrect settings for QUOTED IDENTIFIERS. This might be a red herring but I am at a loss as to the underlying problem and would welcome some input.
Errors:
Ah it seems I'm not permitted to insert images so its a little difficult to share the problem. The error message says
Executing <sp_name> procedure SQLSTATS=42000 Microsoft SQL Server Native Client 10.0 Must declare the scalar variable
The stored procedure script with name masked:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE PROCEDURE [dbo].[xxxxxxxx]
#sTable varchar(40),
#lnew_id integer OUTPUT
AS
BEGIN
SET #lnew_id = -1;
SET #sTable = UPPER(#sTable);
SELECT #lnew_id = id_lastused
FROM idnext WITH (UPDLOCK, ROWLOCK)
WHERE id_table = #sTable;
IF ##error = 0
BEGIN
IF (#lnew_id IS NULL)
BEGIN
SET #lnew_id = -1;
END
IF (#lnew_id >= 0)
BEGIN
BEGIN TRANSACTION tu
SET #lnew_id = #lnew_id + 1
UPDATE idnext
SET id_lastused = #lnew_id
WHERE id_table = #sTable;
IF (##error = 0)
BEGIN
COMMIT TRANSACTION tu;
END
ELSE
BEGIN
ROLLBACK TRANSACTION tu;
SET #lnew_id = -999;
END
END
ELSE
BEGIN
SET #lnew_id = 1;
BEGIN TRANSACTION ti
INSERT INTO idnext (id_table, id_lastused)
VALUES (#sTable, #lnew_id);
IF (##error = 0)
BEGIN
COMMIT TRANSACTION ti;
END
ELSE
BEGIN
ROLLBACK TRANSACTION ti;
SET #lnew_id = -998;
END
END
END
ELSE
BEGIN
SET #lnew_id = -997;
END
RETURN (#lnew_id);
END

Invalid usage of the option flush_interval_seconds in the ALTER DATABASE statement

I have created a database project in visual studio, but when I publish I get the error:
Invalid usage of the option flush_interval_seconds in the ALTER DATABASE statement
And the code that is generated is:
Msg 153, Level 15, State 5, Line 5
Invalid usage of the option flush_interval_seconds in the ALTER DATABASE statement.
(43,0): SQL72045: Script execution error. The executed script:
IF EXISTS (SELECT 1
FROM [master].[dbo].[sysdatabases]
WHERE [name] = N'$(DatabaseName)')
BEGIN
ALTER DATABASE [$(DatabaseName)]
SET QUERY_STORE (DATA_FLUSH_INTERVAL_SECONDS = 0, INTERVAL_LENGTH_MINUTES = 0)
WITH ROLLBACK IMMEDIATE;
END
SQL72014: .Net SqlClient Data Provider:
Msg 153, Level 16, State 6, Line 5
Invalid usage of the option interval_length_minutes in the ALTER DATABASE statement.
(43,0): SQL72045: Script execution error. The executed script:
IF EXISTS (SELECT 1
FROM [master].[dbo].[sysdatabases]
WHERE [name] = N'$(DatabaseName)')
BEGIN
ALTER DATABASE [$(DatabaseName)]
SET QUERY_STORE (DATA_FLUSH_INTERVAL_SECONDS = 0, INTERVAL_LENGTH_MINUTES = 0)
WITH ROLLBACK IMMEDIATE;
END
An error occurred while the batch was being executed.
I am struggling to find any reference on this, and what causes it, and ultimately how to fix it, so any guidance is appreciated.
Edit: the above SQL is auto generated when the DB is published from Visual Studio
A zero value for DATA_FLUSH_INTERVAL_SECONDS doesn't make sense as the value is for the asynchronous flush. I think 60 seconds is the minimum. Also, 1 minute is the minimum for INTERVAL_LENGTH_MINUTES, the size of the fixed-length statistics time window.
You could set it up using Visual Studio.
Solution Explorer-> Database Project -> Right Click -> Properties -> Project Settings -> Database Settings -> Query Store
Change 0 to desired value.
Related: SSDT: SQL Project Options and Database Project Settings
If this does not work, it means that you have custom SQL Script in Pre/Post Deployment folder.

SQL Server trigger firing 3 times

I have set up the following audit trigger to create copies of the record changes into my change log (should we ever need to see what happened to our data). The problem is every time I update the record, it creates 3 records in my log table.
Below you can see the result set and my code I have been using.
Code:
/* ==Scripting Parameters==
Source Server Version : SQL Server 2016 (13.0.4446)
Source Database Engine Edition : Microsoft SQL Server Standard Edition
Source Database Engine Type : Standalone SQL Server
Target Server Version : SQL Server 2017
Target Database Engine Edition : Microsoft SQL Server Standard Edition
Target Database Engine Type : Standalone SQL Server
*/
USE [STONE_DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tr_set_for_update_audit_fields]
ON [dbo].[permission_types]
FOR UPDATE
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO STONE_DB_CHANGE_LOGS.dbo.permission_types_log ([permission_type_id], [business_process], [active], [created_at], [created_by], [change_type], [change_user], [change_at])
SELECT DISTINCT
inserted.id,
inserted.[business_process], inserted.[active],
inserted.[created_at], inserted.[created_by],
'U', SYSTEM_USER, GETDATE()
FROM
inserted
WHERE
1 = 1
AND inserted.[created_at] < getdate();
UPDATE [dbo].[permission_types]
SET updated_at = GETDATE(), updated_by = SYSTEM_USER
FROM [dbo].[permission_types]
INNER JOIN inserted ON permission_types.id = inserted.id
WHERE 1 = 1
--AND permission_types.updated_at < getdate()
;
PRINT 'Record Updated'
END
You need to prevent a database trigger from recursing
Check this solution
How do I prevent a database trigger from recursing?
You should add at the begin of trigger code like this:
IF NOT UPDATE(business_process)
RETURN;
More info: UPDATE()
USE the following code to avoid nesting
IF((SELECT trigger_nestlevel() ) > 1)
RETURN

RAISERROR Syntax error in SQL Server 2014

I'm working on migrating SQL Server 2008 R2 database to SQL Server 2014. Having trouble with the following trigger. Looks like something with RAISEERROR is not supported in newer version.
ALTER TRIGGER [dbo].[Route_ITrig]
ON [dbo].[Route]
FOR INSERT AS
/*
* PREVENT NULL VALUES IN 'RouteName'
*/
IF (SELECT Count(*) FROM inserted WHERE RouteName IS NULL) > 0
BEGIN
RAISERROR 44444 'Field ''RouteName'' cannot contain a null value.'
ROLLBACK TRANSACTION
END
This is the error I'm getting
Msg 102, Level 15, State 1, Procedure Route_ITrig, Line 15
Incorrect syntax near '44444'
This is a SQL function, hence all required variables must be passed in brackets, as follows:
RAISERROR(44444, 'Field ', 'RouteName', ' cannot contain a null value.')

ALTER DATABASE [...] SET SINGLE_USER WITH NO_WAIT waits 20 seconds

On SQL Server 2012, when I am issuing a statement
ALTER DATABASE [...] SET SINGLE_USER WITH NO_WAIT
and someone else is using the database, I have to wait for approximately 20 seconds until the request fails, despite the NO_WAIT termination clause.
Is it possible to tell SQL Server to let the "ALTER DATABASE" request fail immediately? Preferrably also for older versions of SQL Server? (although it seems that "ALTER DATABASE [...] SET" is not supported in SQL Server 2005 and earlier).
Give this a try. It checks for active connections to the database before trying to put it into SINGLE_USER mode.
use master
GO
DECLARE #DBName SYSNAME = N'YourDbName'
IF NOT EXISTS (
SELECT sd.Name, sp.*
FROM sys.sysprocesses sp
JOIN sys.sysdatabases sd
ON sd.dbid = sp.dbid
WHERE sd.Name = #DBName
AND sp.spid <> ##SPID
)
BEGIN
ALTER DATABASE [...]
SET SINGLE_USER WITH NO_WAIT
END

Resources