Category Archives: Imported from BeyondRelational

These posts are imported from my old blog page: http://beyondrelational.com/modules/2/blogs/77/nakuls-blog.aspx

#0161 – SQL Server 2012–Deprecated Features-CREATE TRIGGER-WITH APPEND option


There would hardly be a database developer who hasn’t written triggers in their career. It is fairly common knowledge that you can have more than one trigger of the same type, i.e. INSERT/UPDATE/DELETE on the same table. Therefore, the following is perfectly valid:

USE tempdb
GO
CREATE TABLE dbo.AppendTriggerTest (RowId INT IDENTITY(1,1),
                                    RowValue VARCHAR(50)
                                   )
GO

CREATE TRIGGER dbo.MainTrigger
ON dbo.AppendTriggerTest
FOR INSERT
AS
BEGIN
  PRINT '<<<< INFO >>>> Main Trigger fired...'
END
GO

CREATE TRIGGER dbo.AppendTrigger
ON dbo.AppendTriggerTest
FOR INSERT
AS
BEGIN
  PRINT '<<<< INFO >>>> Append Trigger fired...'
END
GO

However, this was not the case in the days of SQL Server 6.5. In order to have a more than one trigger of the same type on the same table, the WITH APPEND clause needs to be used, which is effectively interpreted as AFTER. In the days of SQL Server 6.5, the trigger “AppendTrigger” will need to be defined as:

CREATE TRIGGER dbo.AppendTrigger
ON dbo.AppendTriggerTest
FOR INSERT
WITH APPEND     --NOTICE THE WITH APPEND CLAUSE HERE, 
                --DEPRECATED FROM SQL 2012 ONWARDS
AS
BEGIN
  PRINT '<<<< INFO >>>> Append Trigger fired...'
END
GO

Starting SQL Server 2012, the compatibility levels lower than 90 (i.e. SQL Server 2000 and below) are no longer supported. In accordance to this, the WITH APPEND clause has also been deprecated.

I assume that you are not using this in your production code, if you are, please upgrade! There is no workaround/alternate to this.

Reference:

Until we meet next time,

Be courteous. Drive responsibly.

#0160-SQL Server 2012–Deprecated Features-32-bit systems – AWE (Address Windowing Extensions) no longer supported


For anybody who has worked with software products or recently bought a new piece of computer hardware, the terms “32-bit support” and “64-bit support” would be familiar.


One of the prime differences between the 32-bit & 64-bit systems is the amount of memory that can be addressed by the operating system. 32-bit systems cannot address a memory space that is greater than 3GB. While 64-bit systems can run a 32-bit application under the Windows-On-Windows shell, these applications would not be able to take advantage of the increased memory addressing capabilities of the underlying operating system. Insufficient memory on a SQL Server host puts the system under undue memory pressure . Memory management is therefore a tricky and critical issue for 32-bit applications running on 64-bit environments.


SQL Server 2005 introduced a switch on the SQL Server instance that allows the instance to use “AWE” (Address windowing extensions) for memory allocation. What this switch does is that it allows a 32-bit instance of SQL Server to access memory that is greater than 3GB. The screen-show below shows the location of this switch in the “Server Properties” dialog of the SSMS for SQL Server 2008.


image


Server properties dialog for SQL Server 2008


However, things are changing with SQL Server 2012 – Address Windowing Extensions (AWE) is no longer supported.


image


Server properties dialog for SQL Server 2012


This switch also has an equivalent advanced option called – “awe enabled”. Attempting to access this option in SQL Server 2012 results in an error.

–Display advanced configuration options
sp_configure ‘show advanced options’,1
RECONFIGURE
GO
–Attempt to fetch the value of the AWE flag
sp_configure ‘awe enabled’
GO
–Hide advanced configuration options
sp_configure ‘show advanced options’,0
RECONFIGURE
GO

Here’s the result:


Configuration option ‘show advanced options’ changed from 0 to 1. Run the RECONFIGURE statement to install.
Msg 15123, Level 16, State 1, Procedure sp_configure, Line 62
The configuration option ‘awe enabled’ does not exist, or it may be an advanced option.

Configuration option ‘show advanced options’ changed from 1 to 0. Run the RECONFIGURE statement to install.


Soltuions

There are no workarounds to this (in my opinion, teams shouldn’t even be thinking in this direction). It is imperative that the 64-bit edition of the SQL Server must be used in order to access over 4GB of physical memory.

References:



Until we meet next time,


Be courteous. Drive responsibly.

#0160-SQL Server 2012–Deprecated Features-32-bit systems – AWE (Address Windowing Extensions) no longer supported


For anybody who has worked with software products or recently bought a new piece of computer hardware, the terms “32-bit support” and “64-bit support” would be familiar.


One of the prime differences between the 32-bit & 64-bit systems is the amount of memory that can be addressed by the operating system. 32-bit systems cannot address a memory space that is greater than 3GB. While 64-bit systems can run a 32-bit application under the Windows-On-Windows shell, these applications would not be able to take advantage of the increased memory addressing capabilities of the underlying operating system. Insufficient memory on a SQL Server host puts the system under undue memory pressure . Memory management is therefore a tricky and critical issue for 32-bit applications running on 64-bit environments.


SQL Server 2005 introduced a switch on the SQL Server instance that allows the instance to use “AWE” (Address windowing extensions) for memory allocation. What this switch does is that it allows a 32-bit instance of SQL Server to access memory that is greater than 3GB. The screen-show below shows the location of this switch in the “Server Properties” dialog of the SSMS for SQL Server 2008.


image


Server properties dialog for SQL Server 2008


However, things are changing with SQL Server 2012 – Address Windowing Extensions (AWE) is no longer supported.


image


Server properties dialog for SQL Server 2012


This switch also has an equivalent advanced option called – “awe enabled”. Attempting to access this option in SQL Server 2012 results in an error.

~~~–Display advanced configuration options
sp_configure ‘show advanced options’,1
RECONFIGURE
GO
–Attempt to fetch the value of the AWE flag
sp_configure ‘awe enabled’
GO
–Hide advanced configuration options
sp_configure ‘show advanced options’,0
RECONFIGURE
GO~~~

Here’s the result:


Configuration option ‘show advanced options’ changed from 0 to 1. Run the RECONFIGURE statement to install.
Msg 15123, Level 16, State 1, Procedure sp_configure, Line 62
The configuration option ‘awe enabled’ does not exist, or it may be an advanced option.

Configuration option ‘show advanced options’ changed from 1 to 0. Run the RECONFIGURE statement to install.


Soltuions

There are no workarounds to this (in my opinion, teams shouldn’t even be thinking in this direction). It is imperative that the 64-bit edition of the SQL Server must be used in order to access over 4GB of physical memory.

References:



Until we meet next time,


Be courteous. Drive responsibly.

#0159-SQL Server-Row Constructors-Triggers process the entire batch at once


Almost every product comes with a set of predefined system default data, which may or may not be editable by the user. When writing about returning result sets from  triggers, I realized that there are very few product teams who use row constructors (introduced in SQL Server 2008) to populate their default data.


What these teams fail to realize is that many a times, the conventional approach may have a negative impact on the time it takes to insert the data and also reduces the overall efficiency of the entire data load operation. Let’s see a demo.


The Test Setup


To demonstrate the point, I will create a small table in the tempdb database with an INSERT trigger on it that would return us the inserted values from the INSERTED view.

USE tempdb
GO
CREATE TABLE dbo.RowConstructorDemo (RowId INT IDENTITY(1,1),
                                     RowValue VARCHAR(30),
                                     RowDescription VARCHAR(100)
                                    )
GO

CREATE TRIGGER dbo.trig_RowConstructorDemo_Insert
ON dbo.RowConstructorDemo
FOR INSERT
AS
BEGIN
  --Some business logic here
  SELECT ROW_NUMBER() OVER (ORDER BY inserted.RowId) AS [RowNumber],
         inserted.RowId,
         inserted.RowValue,
         inserted.RowDescription
  FROM inserted
END
GO

The Conventional Method


Now, let us try to insert a couple of rows using the conventional style of data insertion, i.e. row-by-row approach.

#0158-SQL Server-Returning result sets from triggers


This week, I am taking a brief break from my series on deprecated features of SQL Server 2012 to share with you two experiences I had recently. A developer had suspected that one of the triggers in the database had an issue. To debug this, the developer placed a simple SELECT statement within the trigger.

Below is an example reproducing the scenario for demonstration purposes.

--Use tempdb for demonstration purposes
USE tempdb
GO

--Create a demo table
CREATE TABLE dbo.TriggerResultSets (IdCol INT IDENTITY(1,1),
                                    IdName VARCHAR(50)
                                   )
GO

--Create a trigger that returns a result set
CREATE TRIGGER dbo.trig_TriggerResultSets
ON dbo.TriggerResultSets
FOR INSERT
AS
BEGIN
    /*Some business logic here*/
    SELECT INSERTED.IdCol, INSERTED.IdName
    FROM [INSERTED]
    ORDER BY INSERTED.IdCol
END
GO

Upon inserting some data into our demo table, TriggerResultSets, the developer could see the data that was inserted.

--Insert some test data
INSERT INTO dbo.TriggerResultSets (IdName)
VALUES ('Microsoft'),
       ('SQLServer')
GO

image

The Problem

After resolving the issue that the developer had encountered, the team proceeded to unit test the application, which failed. This was because the SELECT statement was left behind, and the application was not written to handle result sets from triggers.

While the ultimate solution to prevent such a situation in the future is to have proper code review checklists, techniques and methods that would help ensure such code never gets “deployed”, there are workarounds for which developers can be educated for, and a check that all database administrators can use to trap any fall-through occurrences.

The Workaround

The workaround is actually quite simple. Developers can be educated to use PRINT statements instead of the SELECT statements. Because PRINT does not return result sets, the application will remain “happy” and at work as expected. Although, please note that I am not very much in favour of this because data is being exposed here unnecessarily.

--CREATE TABLE statement removed for sake of brevity.

--Create a trigger that returns a result set
CREATE TRIGGER dbo.trig_TriggerResultSets
ON dbo.TriggerResultSets
FOR INSERT
AS
BEGIN
    /*Some business logic here*/
    DECLARE @InsertedId INT
    DECLARE @InsertedName VARCHAR(50)

    SELECT @InsertedId = inserted.IdCol, @InsertedName = inserted.IdName
    FROM [INSERTED]
    ORDER BY INSERTED.IdCol
     
    PRINT 'Id = ' + CAST(@InsertedId AS VARCHAR(10)) + ', Name = ' + ISNULL(@InsertedName,'')
END
GO

INSERT INTO dbo.TriggerResultSets (IdName)
VALUES ('SQLServer')
GO

/*
Result Set:
Id = 1, Name = SQLServer
*/

image

The Check

Despite the proper developer education, multiple checklists and code reviews, it is quite possible that sometimes things may slip through. In such cases (or until the developer education does not complete), the DBA may need to take extreme steps such as completely disabling functionalities that may cause problems. In the case I am referring to, I turned ON a configuration option – disallow results from triggers. Please note that this is an advanced option.

sp_configure 'show advanced options',1
RECONFIGURE
GO

sp_configure 'disallow results from triggers',1
RECONFIGURE
GO

Once turned ON, the original code with the SELECT statement would fail.

INSERT INTO dbo.TriggerResultSets (IdName)
VALUES ('Microsoft'),
       ('SQLServer')
GO

Msg 524, Level 16, State 1, Procedure trig_TriggerResultSets, Line 9

A trigger returned a resultset and the server option ‘disallow results from triggers’ is true.

PLEASE NOTE

Please note that the “disallow results from triggers” option has been marked as deprecated from SQL Server 2008 onwards and now that SQL Server 2012 is out, it will be removed from the next version of SQL Server. Future versions of SQL Server will not support returning result sets from triggers and hence the switch is no longer required.

Per Microsoft’s recommendation, I have turned the switch to 1 in my environments.

Read more about this announcement here: http://msdn.microsoft.com/en-us/library/ms186337(v=sql.110).aspx

Until we meet next time,

Be courteous. Drive responsibly.