alter stored procedure to use snapshot isolation level - sql-server

Quick question I have a database with snapshot enabled using
ALTER DATABASE myDB
SET ALLOW_SNAPSHOT_ISOLATION ON
I'm trying to alter an existing stored procedure to use the transaction isolation level to read uncommitted using as follows:
USE [myDB]
GO
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
GO
/****** Object: StoredProcedure [dbo].[myStoredProcedure] Script Date: 03/27/2012 11:39:24 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[myStoredProcedure]
AS
BEGIN
SELECT *
FROM someTable
END
RETURN 0
But when I reopen the stored procedure the SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED statement is gone.
USE [myDB]
GO
/****** Object: StoredProcedure [dbo].[myStoredProcedure] Script Date: 03/27/2012 11:39:24 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[myStoredProcedure]
AS
BEGIN
SELECT *
FROM someTable
END
RETURN 0
Was the transaction level actually set? I expected the statement to still be there after closing and reopening the stored procedure window. Just wanted to verify, thanks.

You have to put it in the procedure body. If it is outside you are just altering it in that isolation level as opposed to altering the procedure definition to use it.
USE [myDB]
GO
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[myStoredProcedure]
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT *
FROM someTable
END

Related

Switching a user in SQL Server fails when accessing through user's default schema in stored proc

I'm trying to implement shared API in MS SQL Server 2014 DB. In that architecture, schemas should have similar structures and use shared API owned by dbo whereas at the same time exposes own API. To call one another without qualifying object names, EXECUTE AS USER statement is used for context switching to a certain default schema of the current user.
The problem is here: while immediate access with user context switching works fine (e.g. EXECUTE AS USER followed by SELECT * from test_tbl;), the access through default schema in a stored procedure fails with error Msg 208, Level 16, State 1.
Before posting my question, I tried a lot of experiments and tests and searched MSDN, Web and SQL forums for any clue during several days with no luck.
Scripts for reproducing (<MDF> and <LDF> requires substitutions with appropritate file paths):
-- DB creation
CREATE DATABASE [test_sql]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'test_sql', FILENAME = N'<MDF>' , SIZE = 5120KB , FILEGROWTH = 1024KB )
LOG ON
( NAME = N'test_sql_log', FILENAME = N'<LDF>' , SIZE = 2048KB , FILEGROWTH = 10%)
COLLATE Cyrillic_General_CI_AS
GO
ALTER DATABASE [test_sql] SET COMPATIBILITY_LEVEL = 120
GO
ALTER DATABASE [test_sql] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [test_sql] SET ANSI_NULLS OFF
GO
ALTER DATABASE [test_sql] SET ANSI_PADDING OFF
GO
ALTER DATABASE [test_sql] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [test_sql] SET ARITHABORT OFF
GO
ALTER DATABASE [test_sql] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [test_sql] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [test_sql] SET AUTO_CREATE_STATISTICS ON
GO
ALTER DATABASE [test_sql] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [test_sql] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [test_sql] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [test_sql] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [test_sql] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [test_sql] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [test_sql] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [test_sql] SET DISABLE_BROKER
GO
ALTER DATABASE [test_sql] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [test_sql] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [test_sql] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [test_sql] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [test_sql] SET READ_WRITE
GO
ALTER DATABASE [test_sql] SET RECOVERY FULL
GO
ALTER DATABASE [test_sql] SET MULTI_USER
GO
ALTER DATABASE [test_sql] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [test_sql] SET TARGET_RECOVERY_TIME = 0 SECONDS
GO
ALTER DATABASE [test_sql] SET DELAYED_DURABILITY = DISABLED
GO
USE [test_sql]
GO
IF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'PRIMARY') ALTER DATABASE [test_sql] MODIFY FILEGROUP [PRIMARY] DEFAULT
GO
-- Srv login, DB user and schema creation
CREATE LOGIN [test_usr_login] WITH PASSWORD=N'test_usr_login', DEFAULT_DATABASE=[test_sql], DEFAULT_LANGUAGE=[us_english], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO
CREATE USER [test_usr] FOR LOGIN [test_usr_login] WITH DEFAULT_SCHEMA=[test_schema]
GO
CREATE SCHEMA [test_schema] AUTHORIZATION [test_usr]
GO
-- Table and stored proc creation
IF OBJECT_id("[test_schema].[test_tbl]", "U") IS NOT NULL
DROP TABLE [test_schema].[test_tbl];
GO
CREATE TABLE [test_schema].[test_tbl](
[tc] [nchar](10) NULL
) ON [PRIMARY]
GO
IF OBJECT_id("[dbo].[TA]", "P") IS NOT NULL
DROP PROCEDURE [dbo].[TA];
GO
CREATE PROCEDURE [dbo].[TA] AS BEGIN
SET NOCOUNT ON;
SELECT * FROM
(VALUES
('CURRENT_USER', CURRENT_USER),
('SCHEMA_NAME', SCHEMA_NAME()),
('have_UNqualified_select', cast(HAS_PERMS_BY_NAME("[test_tbl]", "OBJECT", "SELECT") as nchar(10))),
('have_qualified_select', cast(HAS_PERMS_BY_NAME("[test_schema].[test_tbl]", "OBJECT", "SELECT") as nchar(10)))
) AS tmptbl([key], val); -- select permissions fro [test_tbl] of the current user
SELECT tc as qualified_tc FROM [test_schema].[test_tbl]; -- qualified select
SELECT tc as UNqualified_tc from [test_tbl]; -- unqualified select fails with Msg 208
END
GO
GRANT EXECUTE ON [dbo].[TA] TO [test_usr]
GO
Test script:
USE [test_sql]
GO
DECLARE #return_value int
execute as login = N'test_usr_login'; -- even when logged in with test_usr_logn, Msg 208 occurs
EXEC #return_value = [dbo].[TA]
revert
SELECT 'Return Value' = #return_value
GO
Output message:
Msg 208, Level 16, State 1, Procedure TA, Line 14 Invalid object name
'test_tbl'.
(1 row(s) affected)
Output result:
key val
CURRENT_USER test_usr
SCHEMA_NAME test_schema
have_UNqualified_select 1
have_qualified_select 1
I would appreciate anyone who could bring light to the solution to the problem described.
The problem is here: while immediate access with user context
switching works fine (e.g. EXECUTE AS USER followed by SELECT * from
test_tbl;), the access through default schema in a stored procedure
fails with error Msg 208, Level 16, State 1.
The problem here is that you don't know how SQL Server resolves non qualified object name.
When you execute plain sql and use an object without specifying its schema, first user default schema is checked, if object is not found, dbo schema is checked. If the object is not found even in dbo, the error is raised.
It's different when it comes to stored procedure. If schema is not specified, sp's schema is checked first, if object is not found, dbo schema is checked, if it's not found again the error is raised. User default schema is never checked in case of stored procedure

how to access a column of a table via foreign key?

I am new in SQL server and having trouble with this trigger code. Can you please tell me what is wrong with this line: set NazivFirme=(select NazivFirme from inserted)... This is where I get an error.
USE [BazaPreduzece]
GO
/****** Object: Trigger [dbo].[promenaNazivaFirme] Script Date: 2017-03-28 5:29:47 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER trigger [dbo].[promenaNazivaFirme]
on [dbo].[Firma]
AFTER UPDATE
as
declare #FirmaID int
select #FirmaID=FirmaID from inserted
if update (NazivFirme)
begin
alter table Vlasnik disable trigger zabranaAzuriranjaNazivaFirme
update [dbo].[Vlasnik]
set NazivFirme=(select NazivFirme from inserted)
where FirmaID=#FirmaID
alter table Vlasnik enable trigger zabranaAzuriranjaNazivaFirme
end
That's theFirma and the Vlasnik tables...

'CREATE/ALTER PROCEDURE' must be the first statement in a query batch

I am trying to create a stored procedure in the database called DB_Interface like this:
USE [DB_Interface]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER PROCEDURE [dbo].[ProcToCCreate]
It throws error:
Msg 156, Level 15, State 1, Line 6
Incorrect syntax near the keyword 'OR'.
Msg 111, Level 15, State 1, Line 10
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.`
This is my first stored procedure - not sure if I cannot use Create or Alter like I used it. Any help is greatly appreciated
CREATE OR ALTER PROCEDURE [dbo].[ProcToCCreate]
AS
RETURN;
is allowed Syntax in (probably) SQL-Server 2016 (only tested on SQL-Server 2016 with SP1)
CREATE PROCEDURE [dbo].[ProcToCCreate]
OR
CREATE PROC [dbo].[ProcToCCreate]
are only valid syntax in SQL Server.
If you want to ALTER procedure, here is the syntax
ALTER PROCEDURE [dbo].[ProcToCCreate]
CREATE:
USE [DB_Interface]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[ProcToCCreate]
AS
RETURN
ALTER:
USE [DB_Interface]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ProcToCCreate]
AS
RETURN

Database script not executing in SQL Server 2008

In my SQL Server 2008 R2, I have a database script which generates successfully, but when I am trying to execute that script it only shows Executing query message and nothing happen.
I had waited at-least 10 minutes for result but force fully I have to stop executing that query.
Note: All other queries are working normally, but only database script is not executing as explained above
I don't know what's going on...
More details: This thing is not happening on particular DataBase, it is a problem on all the database of my SQL Server.
lets see it by example.
In SQL Server 2008 R2, I have following type of script.
USE [master]
GO
/****** Object: Database [BillingApplication] Script Date: 01/22/2013 17:42:04 ******/
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'BillingApplication')
BEGIN
CREATE DATABASE [BillingApplication] ON PRIMARY
( NAME = N'BillingApplication', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\BillingApplication.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'BillingApplication_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\BillingApplication_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
END
GO
ALTER DATABASE [BillingApplication] SET COMPATIBILITY_LEVEL = 100
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [BillingApplication].[dbo].[sp_fulltext_database] #action = 'enable'
end
GO
ALTER DATABASE [BillingApplication] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [BillingApplication] SET ANSI_NULLS OFF
GO
ALTER DATABASE [BillingApplication] SET ANSI_PADDING OFF
GO
ALTER DATABASE [BillingApplication] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [BillingApplication] SET ARITHABORT OFF
GO
ALTER DATABASE [BillingApplication] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [BillingApplication] SET AUTO_CREATE_STATISTICS ON
GO
ALTER DATABASE [BillingApplication] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [BillingApplication] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [BillingApplication] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [BillingApplication] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [BillingApplication] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [BillingApplication] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [BillingApplication] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [BillingApplication] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [BillingApplication] SET DISABLE_BROKER
GO
ALTER DATABASE [BillingApplication] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [BillingApplication] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [BillingApplication] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [BillingApplication] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [BillingApplication] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [BillingApplication] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [BillingApplication] SET HONOR_BROKER_PRIORITY OFF
GO
ALTER DATABASE [BillingApplication] SET READ_WRITE
GO
ALTER DATABASE [BillingApplication] SET RECOVERY FULL
GO
ALTER DATABASE [BillingApplication] SET MULTI_USER
GO
ALTER DATABASE [BillingApplication] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [BillingApplication] SET DB_CHAINING OFF
GO
EXEC sys.sp_db_vardecimal_storage_format N'BillingApplication', N'ON'
GO
USE [BillingApplication]
GO
/****** Object: Table [dbo].[tbCustBill] Script Date: 01/22/2013 17:42:07 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tbCustBill]') AND type in (N'U'))
BEGIN
-- And continue the entire script
Now as I had seen in SQL Server Profiler than the execution till following code work perfectly.
ALTER DATABASE [BillingApplication] SET RECURSIVE_TRIGGERS OFF
GO
And on the the next line executing become stop.
I don't know what's going on....
On force full stop of execution its generate error as below
Msg 5069, Level 16, State 1, Line 1
ALTER DATABASE statement failed.
So, that's it may be some SQL Sever configuration problem...
I think you need to ensure you can place an exclusive lock on the database to change this setting. Even though you just created the database you may have established more than one connection to it. Make sure you disable IntelliSense in Management Studio, that you have no other windows connected to this database, and that you switch context to another database. Then set the database to single user, make your changes, and set it back:
USE master;
GO
ALTER DATABASE BillingApplication SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
ALTER DATABASE BillingApplication SET RECURSIVE_TRIGGERS OFF;
GO
ALTER DATABASE BillingApplication SET DISABLE_BROKER;
GO
... other changes ...
ALTER DATABASE BillingApplication SET MULTI_USER;
GO
If this still waits then you may be waiting on some very large transaction to roll back, and you can check in another window what you are waiting for by looking at sys.dm_exec_requests and/or sys.dm_os_waiting_tasks.
Though, if you are creating the database, why do you think you need to explicitly disable broker? It's not enabled by default...
You have
ALTER DATABASE [BillingApplication] SET DISABLE_BROKER
without ane ON or OFF. Set that and it should work.
Nope, that's not it. I'd guess it has something to do with the Service Broker sub-system, but that's not something I'm familiar with. Hopefully someone else who knows that system can answer this...\

How to set "SET XACT_ABORT ON " in a SQL Server transaction?

I want to set SET XACT_ABORT ON in a SQL Server 2008R2 stored procedure with a transaction, so do it in a creation script:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET XACT_ABORT ON
GO
CREATE PROCEDURE MyProc
AS
BEGIN TRAN
...
IF ##ERROR <> 0
BEGIN
GOTO Done
END
...
IF ##ERROR <> 0
BEGIN
GOTO Done
END
COMMIT TRAN
Done:
IF ##ERROR <> 0
BEGIN
ROLLBACK TRAN
END
GO
After successful creation, I check the transaction by clicking "Modify" stored procedure option and in a generated ALTER PROCEDURE script I don't see SET XACT_ABORT ON line:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE MyProc
AS
BEGIN TRAN
...
Where am I wrong or what is the trick? How to correctly define SET XACT_ABORT ON?
You normally set xact_abort as part of the body of the stored procedure:
CREATE PROCEDURE MyProc
AS
SET XACT_ABORT ON
BEGIN TRAN
....
There are two "special" settings that are remembered from the session that created the procedure. Explanation from MSDN:
Stored procedures execute with the SET settings specified at execute
time except for SET ANSI_NULLS and SET QUOTED_IDENTIFIER. Stored
procedures specifying SET ANSI_NULLS or SET QUOTED_IDENTIFIER use the
setting specified at stored procedure creation time. If used inside a
stored procedure, any SET setting is ignored.
So when you create a stored procedure, SQL Server copies the QUOTED_IDENTIFIER option from the connection to the procedure definition. The goal is that someone else with a different QUOTED_IDENTIFIER setting still gets the behavior the author of the procedure intended.
The same is not true for XACT_ABORT.
You didn't mention whether or not you are using SQL Management Studio, but if you are and click "Modify" on an existing stored procedure (which I'm assuming is what you did) then MS just generates a boilerplate script based on the contents of the existing stored procedure.
You might consider defining your stored procedures in a separate script file that performs and ALTER PROCEDURE, plus whatever other options you want outside of the sproc (such as SET XACT_ABORT ON). That way you have more control and can just execute the script to update the sproc.

Resources