Session Session VDA308VDA308
Achieve the Impossible:Achieve the Impossible:Use INSTEAD OF triggers in SQL Use INSTEAD OF triggers in SQL Server 2000 to Deal Transparently Server 2000 to Deal Transparently
with No-updateable Viewswith No-updateable Views
Fernando G. GuerreroFernando G. GuerreroSQL Server MVPSQL Server MVP
.NET Technical Lead.NET Technical LeadQA plcQA plc
October 2002October 2002
VS .NET ConnectionsVS .NET Connections 2
Quick info about FernandoQuick info about Fernando(2 milliseconds)(2 milliseconds)
QA• MCSD, MCSE+Internet (W2K), MCDBA, MCT,
SQL Server MVP
• This is where I work: QA, The best learning environment in Europe
• Writing for SQL Sever Magazine and SQL Server Professional
• This is my main web site: www.callsql.com
• This is my book (so far):– Microsoft SQL Server 2000 Programming by
Example (ISBN : 0789724499, co-authored with Carlos Eduardo Rojas)
• Currently writing on ADO.NET and SQL Server 2000
VS .NET ConnectionsVS .NET Connections 3
AgendaAgenda
• INSTEAD OF triggers?• Updateable and non-updateable views• Using Instead of triggers to make a view
updateable• How to use this technique from ADO.NET?• Applying this technique to specific scenarios
• Note: slides are just a table of contents, is in the examples (with query plans and SQL Profiler) where you will learn what actually happens
33
VS .NET ConnectionsVS .NET Connections 6
A very silly INSTEAD OF triggerA very silly INSTEAD OF trigger
CREATE TRIGGER allSalesON OrdersINSTEAD OF INSERT, DELETE, UPDATEASPRINT 'Hello'
GO
UPDATE OrdersSET OrderDate = getdate()WHERE OrderID = 10259
VS .NET ConnectionsVS .NET Connections 7
Result of the very silly INSTEAD Result of the very silly INSTEAD OF triggerOF trigger
Hello
(1 row(s) affected)
• But nothing has been changed
• INSTEAD OF updating that row…
• … I printed ‘Hello’
VS .NET ConnectionsVS .NET Connections 8
Be careful with INSTEAD OF Be careful with INSTEAD OF triggerstriggers
• It is up to you to write the appropriate code that will run instead of the requested action
• If you decide to do nothing in your code, NOTHING will be done
VS .NET ConnectionsVS .NET Connections 9
INSTEAD OF triggers and INSTEAD OF triggers and TransactionsTransactions
• Inside the trigger you are always inside a transaction:– If you were inside a transaction already before the
trigger started, @@TRANCOUNT remains unchanged
– Otherwise @@TRANCOUNT returns 1
• If you executed ROLLBACK inside the trigger, the entire transaction will be rolled back:– No need for rolling back this particular action– Inform the calling batch with an error and do nothing
instead
VS .NET ConnectionsVS .NET Connections 10
INSTEAD OF triggers and LocksINSTEAD OF triggers and Locks
• When the trigger starts execution:– No exclusive locks have been obtained by this
particular action– Update locks has been obtained– Intent locks has been obtained at higher levels of
granularity
• As soon as the trigger perform any action locks will be obtained appropriately
• Locks will be released when the transaction terminates
VS .NET ConnectionsVS .NET Connections 11
Order of ExecutionOrder of Execution
1. Default values
2. Instead of Trigger
3. Other constraints (Primary, check, unique)
4. Data is modified
5. IDENTITY and GUID values are evaluated
6. Indexes are maintained
7. Cascade Foreign Keys are applied, if any
8. After triggers run
VS .NET ConnectionsVS .NET Connections 12
So, are INSTEAD OF triggers any So, are INSTEAD OF triggers any good?good?
• They run when it is still time to decide• Less intrusive than AFTER triggers• Improve concurrency by avoiding
exclusive locks as much as possible• Could produce more overhead than
constraints, but less than after triggers• Perhaps better than stored procedures
because you can’t avoid instead of triggers: they always run
VS .NET ConnectionsVS .NET Connections 13
A “little” problem with INSTEAD OF A “little” problem with INSTEAD OF UPDATE triggersUPDATE triggers
• You don’t have a RESEND, or DOIT, statement
• Let’s see why this is important with this example
• Feel free to send your wishes to [email protected]
VS .NET ConnectionsVS .NET Connections 14
Updateable and non-updateable Updateable and non-updateable viewsviews
• As a general rule a view is always updateable unless:– It is collapsed:
• Uses UNION• Is the result of an aggregation
– All its columns are read-only– Doesn’t contain an actual table in the FROM clause
• UNION ALL views can be updateable if they are defined as partitioned views
• As long as there is one column to update, the view can be updated
VS .NET ConnectionsVS .NET Connections 15
What about primary keys?What about primary keys?
• A view doesn’t need a primary key or unique index to be updatable
• Because UPDATE, INSERT or DELETE statements don’t need to reference primary keys at all
• This is a limitation of the Visual Database Tools included in:– Enterprise Manager– Query Analyzer– Visual Studio– Access
VS .NET ConnectionsVS .NET Connections 16
Some misleading info in BOL on Some misleading info in BOL on updateable viewsupdateable views
• Derived columns make a view non updateable… Wrong!– Look at this example
• Views can be updated as long as SQL Server knows how to translate changes to the underlying table… Wrong! unless– It is a properly formed partitioned view– It has defined the appropriate instead of triggers– Look at this example
VS .NET ConnectionsVS .NET Connections 17
What about joins?What about joins?
• Transact-SQL supports JOIN clause in the UPDATE, INSERT and DELETE statements
• Therefore, a view defined with a JOIN clause is updateable as long as:– every statement updates one and only one
table at a time– Or it has defined the appropriate instead of
triggers
VS .NET ConnectionsVS .NET Connections 18
Using Instead of triggers to make Using Instead of triggers to make updateable a non-updateable viewupdateable a non-updateable view
• The instead of trigger runs first, before the actual modification is attempted
• If you know the business meaning of the intended modification, you can write an instead of trigger to do it
• The code inside the instead of trigger will modify actual tables, instead of the view itself
• As long as the code inside the trigger is valid, the action will be valid as well
• All this process is transparent to the user
VS .NET ConnectionsVS .NET Connections 19
How to use this technique from How to use this technique from ADO.NET?ADO.NET?
• The UI doesn’t support this feature, and the DataAdapter will be unable to create the InsertCommand, UpdateCommand and DeleteCommand:– It’s a problem with connection settings
(ARITHABORT) that could be fixed by the VS or SQL guys ([email protected])
• As long as you define your own commands it works fine
VS .NET ConnectionsVS .NET Connections 20
What about the CommandBuilder?What about the CommandBuilder?
• It doesn’t support updateable views through instead of triggers unless:– You set the AIRTHABORT ON connection
option by code– You create a UNIQUE CLUSTERED INDEX on
that view– You use the NOEXPAND option
after the view name– There you go
VS .NET ConnectionsVS .NET Connections 21
Applying this technique to specific Applying this technique to specific scenariosscenarios
• Dealing transparently with vertically partitioned tables
• Dealing transparently with horizontally partitioned tables
• Updating computed columns• Updating summary data
• I’ll show you in detail one example of each one of these scenarios
VS .NET ConnectionsVS .NET Connections 22
Dealing transparently with vertically Dealing transparently with vertically partitioned tablespartitioned tables
• DELETE: – Don’t do it unless you know for sure
what makes sense
• INSERT: – Which table you want to insert to?– Write one statement per table
• UPDATE:– Write one statement per underlying
table
VS .NET ConnectionsVS .NET Connections 23
Dealing transparently with Dealing transparently with horizontally partitioned tableshorizontally partitioned tables
• Define them as partitioned views and leave SQL Server alone, he will do it properly for you
• In any other case, write the appropriate code to select which actual table to affect
• Have a clear partition criteria!
VS .NET ConnectionsVS .NET Connections 24
Updating computed columnsUpdating computed columns
• Make sure the formula has a valid reverse formula which produces unique valid results
• Don’t expect the UI to be able to deal with it at all
VS .NET ConnectionsVS .NET Connections 25
Updating summary dataUpdating summary data
• You should know what means updating totals ;-)
• It could be useful for increasing budget on several unfinished sections with a single change on total budget
• Also for spreading changes on target sales for all salespeople
VS .NET ConnectionsVS .NET Connections 26
Do you want to know more?Do you want to know more?
• “Inside SQL Server 2000” (Kalen Delaney, MSPress)• “Advanced Transact-SQL for SQL Server 2000” (Itzik
Ben-Gan & Tom Moreau, APress)• “SQL Server 2000 Programming” (Robert Vieira, WROX)• “Microsoft SQL Server 2000 Programming by Example”
(Fernando G. Guerrero & Carlos Eduardo Rojas, QUE)• SQL Server 2000 Resource Kit (MSPress & TechNet)• Visit the Microsoft public newsgroups:
– msnews.microsoft.com/microsoft.public.sqlserver.*
• Download the source code of this session from:– http://www.callsql.com/en/articles
2626
VS .NET ConnectionsVS .NET Connections 27
Do you want to know even Do you want to know even more?more?
• Visit the Microsoft public newsgroups:– msnews.microsoft.com/
microsoft.public.sqlserver.*– msnews.microsoft.com/
microsoft.public.dotnet.*
2727
VS .NET ConnectionsVS .NET Connections 28
Thank you! Questions?Thank you! Questions?
• Please drop off your session evaluations in the basket at the back of the room!
• Your comments are greatly appreciated!
• Download the source code of this session from:– http://www.callsql.com/en/articles
• You can contact me at:– [email protected]