Archive

Archive for the ‘T-SQL Reference’ Category

INSERTED and DELETED Logical Tables

February 23, 2009 Leave a comment

The INSERTED and DELETED logical tables that exist in SQL Server and allow for handling the data when information is inserted, updated and deleted in DML Triggers only:

DML trigger statements use two special tables: the deleted table and the inserted tables. SQL Server automatically creates and manages these tables. You can use these temporary, memory-resident tables to test the effects of certain data modifications and to set conditions for DML trigger actions. You cannot directly modify the data in the tables or perform data definition language (DDL) operations on the tables, such as CREATE INDEX. (Books Online, SQL Server 2008).

Below is summary of what special tables get modified with each DML statement.

DML Statement INSERTED DELETED
INSERT X
UPDATE X X
DELETE X

I wanted to know if there anything special happens when I work with single row versus batch. So I test follow cases …

For testing I Created a new table called ‘IDST_Testing’ (IDST = Inserted Deleted Special Table). Below is summary of test cases and records inserted in each of the special tables.

Test Case INSERTED DELETED
Single Insert 1 0
Double Insert – Two Statements 1/per statement 1/per statement
Single Update 1 1
Double Update – Two Statements 1/per statement 1/per statement
Single Delete 0 1
Double Delete – Two Statements 1/per statement 1/per statement
Batch Insert – Two Records 2 0
Batch Update – Two Records 2 2
Batch Delete – Two Records 0 2

All those results are normal; but what was surprising was when I was doing batch INSERTED and DELETED the records were in reverse order.

For example:

I inserted following two records:

John
Mary

But when I looked at INSERTED table it showed:

Mary
John

In my actual table it was in order what I entered in but when processing the INSERTED and DELETED table they are revered. It was same in tables with IDENTITY columns and without.

Another interesting information on these tables:

  1. In SQL Server 2000, these logical tables internally refer to database transaction log to provide data when user queries them.
  2. In SQL Server 2005, these logical tables are maintained in tempdb and they are maintained using the new technology Row versioning.
  3. Accessing of logical tables is much faster in SQL Server 2005 when compared to SQL Server 2000 as the load is removed from transaction log and moved to tempdb.
  4. Logical tables are never indexed. So, if you are going to loop through each and every record available in these tables, then consider copying data of logical tables to temporary tables and index them before looping through.

Ref: http://blog.techdreams.org/2007/01/logical-tables-of-sql-server-inserted.html

Ref: http://www.sqlmag.com/Article/ArticleID/93465/sql_server_93465.html

When creating trigger it is important to keep in mind that sometimes a Batch Import, Update or Delete might happen against the table; if you are referring the logical tables INSERTED and DELETED the data will be in reverse order so you don’t want to cause issues when traversing through these tables in triggers.

Note always keep in mind RBAR when designing triggers; its very easy set up RBAR scenario when working with triggers. For more information on that please read, http://www.simple-talk.com/sql/t-sql-programming/rbar–row-by-agonizing-row/.

Categories: T-SQL Reference

Schema Binding: Views

November 21, 2008 6 comments

Schema Binding is there to stop the accidentally removal of required columns from a table. If SCHEMABINDING is in the create statement of an object it will force SQL Engine to check any changes on the tables against the dependencies to make sure no Schema Bound objects are in conflict with the update. SQL Server does not check dependencies when altering or dropping tables.

Schema Binding can be used with:

  • Functions
  • Views

One of the benefits is the depended object can not be accidentally dropped. SQL Server will return an error as we will see in examples below. Schema Binding exists in SQL Server 2000, 2005, and 2008. In this post I will only address Schema Binding on Views.

Requirements to use Schema Binding for Views:

  • Two-part name of the object (ex. dbo.Table1).
  • Cannot select fields using “*”, must list fields being selected.
  • Tables/Views in the Schema Binding cannot be dropped and alter statement affecting the tables and views which are dependencies for another object will fail.

There are no additional requirements added since the introduction of Schema Binding in SQL Server 2000. The demo below is done in SQL Server 2005.

We will first create a new table which will be used as a base for the views and function calls:

CREATE TABLE SBExample (SBCol1 int,
SBCol2 int,
SBCol3 int)
GO

We will first test out the two-part name and “*” (selecting all fields) conditions to see how SQL Server Engine reacts:

CREATE VIEW SBView WITH SCHEMABINDING
AS

SELECT *
FROM SBExample

GO

Executing the above query, SQL Server returns the following error message:

Msg 1054, Level 15, State 6, Procedure SBView, Line 4
Syntax ‘*’ is not allowed in schema-bound objects.

This requirement message exists to prevent people from binding all the columns in a table; when we create a view, we should be selecting only the required columns. So when you are using Schema Binding in Server Server, the SQL Engine expects a column list. You can still list all the columns if you choose to do so; but you have to cautious because this can run into performance issues. If you are selecting extra columns then needed then SQL Server will not be able to use the proper index (covering or including), thus possibly causing a full table scan to retrieve the information requested.

So let’s modify the code to following query and run again:

CREATE VIEW SBView WITH SCHEMABINDING
AS

SELECT SBCol1
FROM SBExample

GO

This time when we run it we get a different error message:

Msg 4512, Level 16, State 3, Procedure SBView, Line 4
Cannot schema bind view ‘SBView’ because name ‘SBExample’ is invalid for schema binding. Names must be in two-part format and an object cannot reference itself.

This is another restriction on the views; this forces you to bind the view to proper schema-table name combo. In general I have found it to be good practice when writing queries for development project to use at least two-part object name to eliminate confusion where the object resides. Therefore we can modify the code to following to fix this issue:

CREATE VIEW SBView WITH SCHEMABINDING
AS

SELECT SBCol1
FROM dbo.SBExample

GO

And this time our view is created successfully and we get the following message.

Command(s) completed successfully.

Now if we try to drop the table, SBExample, after binding one of the columns from to the view, SBView, lets see what happens.

DROP TABLE SBExample
GO

We get the following message:

Msg 3729, Level 16, State 1, Line 1
Cannot DROP TABLE ‘SBExample’ because it is being referenced by object ‘SBView’.

Notice this time SQL Server was forced to check the dependencies of the table before dropping it; since we were referencing a column from the table in the view, SBView, the SQL Server engine refused to let us drop the table. So let’s alter alter the view and re-create it without SCHEMABINDING.

ALTER VIEW SBView
AS

SELECT SBCol1
FROM dbo.SBExample

GO

Now let’s try to drop the table again:

DROP TABLE SBExample
GO

We get the following message this time:

Command(s) completed successfully.

What happened? We still have the view on top of the table? This time SQL Server didn’t complain when we tried to drop it because the SQL Engine wasn’t forced to check for dependencies. If we try to select from our view now, we should get an error message.

SELECT SBCol1
FROM SBView
GO

As expected we got the following error message:

Msg 208, Level 16, State 1, Line 1
Invalid object name ‘dbo.SBExample’.
Msg 4413, Level 16, State 1, Line 1
Could not use view or function ‘SBView’ because of binding errors.


As you can see this can cause issues, especially when you are creating views on third party applications or in applications in large organizations. When a third party vendor makes changes to their tables they have no way of knowing what dependencies exist outside their application. When they make their changes it can easily break the views that you might have created because the required columns or tables might have been dropped. If you have Schema Binding on your views; when implementing the update in the test environment you should be able to identify the issues and resolve them before going to production. In the bigger organization where you might be jumping from one project to another, you can’t be expected to know all the views and tables in the databases. Sometimes when altering the table you might drop something, which was required by another view. SQL Server does have a built-in manual dependencies checker, so anytime someone is dropping column/table it should be used to make sure it will not break any of the dependent objects.

Now let’s examine what happens to the table when we alter it while it is schema bound to a view. I re-created the original table with the original schema bound view. Now if I alter the table to add a new column, alter an existing column or drop a column; what do we expect to see? Does SQL Server engine allow us to execute it or does it error out?

ALTER TABLE SBExample
ADD SBCol4 int
GO

No Issues.
Now let’s try to alter few columns.

 ALTER TABLE SBExample
ALTER COLUMN SBCol4 bigint
GO

No Issues.

 ALTER TABLE SBExample
ALTER COLUMN SBCol1 varchar(1)
GO

So when we try to alter even just the type of the schema bound column we get an error:

Msg 5074, Level 16, State 1, Line 1
The object ‘SBView’ is dependent on column ‘SBCol1′.
Msg 4922, Level 16, State 9, Line 1
ALTER TABLE ALTER COLUMN SBCol1 failed because one or more objects access this column.

So now let’s try to drop few columns.

ALTER TABLE SBExample
DROP COLUMN SBCol4
GO

No Issues.

ALTER TABLE SBExample
DROP COLUMN SBCol1
GO

If we try to drop the column for schema bound column we get the same error again:

Msg 5074, Level 16, State 1, Line 1
The object ‘SBView’ is dependent on column ‘SBCol1′.
Msg 4922, Level 16, State 9, Line 1
ALTER TABLE DROP COLUMN SBCol1 failed because one or more objects access this column.

So the lesson here is you can alter the table as much as you like as long as you don’t alter the columns that are being referenced. This is another reason why you should only reference the columns needed in the view so it does not stop other people from doing required changes to table. However as good as the schema binding option sounds; there is a draw back. You cannot drop or alter the column on any table that has object bound to it using schema binding. The objects will also need to be dropped before the table can be adjusted.

SQL Server 2005 and SQL Server 2008 books online state “SCHEMABINDING cannot be specified if the view contains alias data type columns”. I have tried everything I know to produce an error; as I far as I can tell this is an error in the books online. I posted on the Microsoft Community Newsgroup, Kalen Delaney (MVP) also thinks it is a mistake.

I then searched through Microsoft Connect to see if any Schema Binding issues were submitted relating to this. I could not find any so I submitted a bug report on Microsoft Connect. If anyone else can find another way to get this error let me know. I also went through System Error messages with no luck. I don’t think its a critical fix, but after playing with SQL Server 2000, 2005, and 2008 for while and not getting the expected results it was a bit frustrating; so I think it should be fixed in the books when time permits.

Microsoft Connect Bug Link: https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=383560

Nov. 24, 2008 – Update

Fixed a lot of my English (I hope) :) . I would like to thank my friends for valuable feedback and corrections :-D .

Added examples for Alter Column. Thanks.

Follow

Get every new post delivered to your Inbox.

Join 150 other followers