Can any one explain in detail with an example if possible, why AFTER triggers are not supported for views in SQL Server?
I know we use AFTER triggers after insert, update or delete on a table, then why not on a view, too?
Because it is only possible to do something instead of an DDL statement on a view.
Views themselves don't contain data, so it is not possible to do something before or after a change since it can't be sure how one change on the view affects the data below it.
Example:
If you have a view resulting in one row, and you update that row, that row might disappear, 'another' row might pop up, and there is no way to tell the relation between the first and the last.
Related
I create a table from a junction between 3 tables.
The issue that I'm facing is that this table becomes outdated once a new modification affects once of the original table used to supply its data.
How should solve this problem? Is a trigger the only solution?
You have several options:
Live with the outdated data and periodically (say once a day or once an hour) update the table.
Use a trigger to update the associated values.
Use a view.
Use an indexed view if possible (see here).
The last option is a way to define a view that SQL Server updates automatically -- what is called a materialized view in other databases. That said, not all queries are supported in materialized views.
"There are two problems in computer science. Cache coherency, and naming things." Tables derived from other tables exemplify both.
SQL Server supports materialized views, if you actually need them. Before you decide you do, do what every good carpenter does: measure twice and cut once. That is, write an ordinary view, and see how fast it is. If it's too slow -- however defined -- find out why. Most of the time, slow views can be sped up using indexes. If you have 100s of millions of rows, you might convert the view to a function that takes an argument applied to the WHERE clause, making it a "parameterized" view.
My team and I are using Microsoft SQL Server 2014 - Standard Edition (64-bit)
We have created some views as we usually do, they work(ed) normally while we were coding and testing.
Then suddenly, one of our QA noticed that the data in the application was mixed up, for example, description data was in the name field, name was where sex was supposed to be, etc.
We cheched data in the Tables and it was correct, then we checked the view, querying the view like this SELECT * FROM VIEW and realized that the view had the data mixed up.. The next logic step was to check the view queries, for our surprise all the queries were correct. so what was happening?
Well, that is the question, why the data in a view is corrupt or mixed up if the queries within the view are correct and they were working well for long time?
We just ALTERED the view, not modifying anything and that fixed the issue.
But, we need to know the cause of the data corruption, because we don't want to monitor and alter views all the time.
VIEW CODE AS REQUESTED
ALTER VIEW [dbo].[pvvClient] AS
SELECT *
FROM Table
INNER JOIN Table 2 ON.....
The first thing that came to my mind was that the Table(s) has changed and that raised this behavior, do you think SCHEMABINDING can help to avoid this kind of issues
When you put * in the column list of a view and the underlying tables change your view will not automatically update to include the changed columns. In fact, if you delete a column you can get the data mixed up across columns. This has been discussed and documented many times. Aaron Bertrand has a great article covering this topic.
Bad habits to kick : using SELECT * / omitting the column list
Moral of the story, avoid using select * unless the select is inside an EXISTS.
It doesn't make sense that simply altering the view without changing any of the code would fix it, but an important point is this part of your view...
select pvtConsumidorFinanciero.*
If this table definition changes... that is, if more columns are added or some are removed, the columns in this view would also change. That is why it is good practice to never select * in a view, especially when querying another view.
Additionally, this table could have the same column names as other tables.
What also could have happened is in your application, you are select * from view. Again, if a DBA changed the view, this could mess up your application, so i would avoid it an explicitly list the columns you want returned in the order you want them returned.
I think this is is also part of the answer:
When you create views it is a good practice to use SCHEMABINDING, this way when you alter the table under the view, you are forced to review your view as well.
Is it possible to delete rows from a View?
Usually, a view isn't something you can delete from; it's kind of a virtual table, which shows you the rows from one or more real tables in the database. If you want a row to disappear from a view, you need to either delete the data from the real tables behind the view, or alter the view-creating SQL so that that particular row won't be shown in the view. With some simpler views you can DELETE FROM (and update) a view; however, even so the data is actually deleted from the real table.
You also cannot generally add anything to a view; if you need completely new data, it has to be added in the real table(s) from which the view is created.
For view basics, see for example http://www.w3schools.com/sql/sql_view.asp
If your view is updatable - really depends on a database you are using and the way view was created. General rule (again, varies from one DB to another) there should be one table and no aggregates in the select statement, creating the view.
Here is details for MySQL: http://dev.mysql.com/doc/refman/5.7/en/view-updatability.html
And for SQL Server: https://msdn.microsoft.com/en-CA/library/ms187956.aspx
InterSystems Caché: http://docs.intersystems.com/cache20152/csp/docbook/DocBook.UI.Page.cls?KEY=GSQL_views#GSQL_views_update
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Just a quick question on my MCSA SQL Server 2012 course.
As part of an exercise I've been asked to create a trigger to stop any updates on a view, I first checked that I could indeed change a value of a column on the view.
Having worked with views before I know what they are, but I dont know why a view wouldn't stop a change in the first place by default anyway.
1) Why might I want to change a value in the view table?
2) Also if I updated a value on the view, would anything change it back to reflect what is in the base tables and if so when might that happen?, ie an overnight refresh, any change to the base table?
Thanks :)
Your question seems to be more concerned with "why" rather than "how." Why would DML be executed against a view instead of directly against a table? The answers are almost too numerable to list here, but here are just a couple of the bigger ones.
For starters, when I design a database, almost every table has at least one view defined for it. If more than one, one is normally the DML view and the others are read-only (trigger that does nothing). No outward-facing and very few inward-facing apps have direct access to the tables. Everything must go through the views.
Why? Because this builds a wall of abstraction between the apps and the underlying tables. I can then constantly tune and tweak the tables and rarely have to make any changes to the apps. I can add or drop columns, change the data type of columns, merge tables together or split a table into two or three separate tables, but the views bring everything back together to how the apps expect to see it. They don't even have to know any changes were made. The apps can write data to what they see as a single "table" and the view trigger assigns the data to the correct tables. The view triggers know how the actual data is stored, the apps don't have to know.
Here's one advantage that is unbeatable. There are many, many useful functions that require the use of a before trigger. Sometimes you just really want to manipulate the data in some way before it goes to the table. Some DBMSs, even major players like SQL Server, have only after triggers. Such a pain.
But front the table with a view, write a trigger on the view, et voila, instant before trigger. This is even handy with other DBMSs like Oracle in that the trigger can update other associated rows in the same table without running afoul of a mutating table condition. I am at this very moment writing a trigger on a view that must update values in several rows every time any Insert or Delete is executed and sometimes for an Update. Almost impossible task without views -- it would have to be done with stored procedures rather than "direct" DML. Handy for me, handy for the apps. Life is good!
Also, take the loop condition caused by trying to keep two tables synched with each other. Any changes made in either table should be sent to the other table. But a trigger on both tables that just mirrors the operation to the other table will create an infinite loop as that trigger turns around and sends it right back. But a trigger on a facing view can perform the DML on its underlying table and on the mirrored table. The view on the mirrored table does the same thing. But since both views operate directly on the tables, there is no infinite loop condition to fall into.
So my question would be more like: why would we ever want users to directly access tables rather than have them go through views?
to answer the question on how to accomplish this with a trigger, you can use the following:
CREATE TRIGGER dbo.demo_trigger ON dbo.demo_view
INSTEAD OF UPDATE --The "INSTEAD OF" is probably why the question is in the course, outside of a view or procedure this is tends to be "BEFORE"
AS
BEGIN
SET NOCOUNT ON
ROLLBACK
RAISERROR (50005,10,1,N'abcde')
END
GO
I added a custom error with this:
sp_addmessage #msgnum = 50005
, #severity = 10
, #msgtext = N'Not allowed';
GO
It can be removed again with this:
sp_dropmessage #msgnum = 50005;
Trying to update the view now gives this result:
Not allowed
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.
Can you update a view in a database?
If so, how?
If not, why not?
The actual answer is "it depends", there are no absolutes.
The basic criteria is it has to be an updateable view in the opinion of the database engine, that is to say can the engine uniquely identify the row(s) to be updated and secondly are the fields updateable. If your view has a calculated field or represents the product of a parent/child join then the default answer is probably no.
However its also possible to cheat... in MS SQL Server and Oracle (to take just two examples) you can have triggers that fire when you attempt to insert or update a view such that you can make something that the server doesn't think updateable into something that is - usually because you have knowledge that the server can't easily infer from the schema.
The correct answer is "it depends". You can't update an aggregate column in a view for example. For Oracle views you can Google for "updatable join view" for some examples of when you can and cannot update a view.
Yes, they are updatable but not always. Views can be updated under followings:
If the view consists of the primary key of the table based on which the view has been created.
If the view is defined based on one and only one table.
If the view has not been defined using groups and aggregate functions.
If the view does not have any distinct clause in its definition.
If the view that is supposed to be updated is based on another view, the later should be updatable.
If the definition of the view does not have any sub queries.
PostgreSQL has RULEs to create updatable VIEWs. Check the examples in the manual to see how to use them.
Ps. In PostgreSQL a VIEW is a RULE, a select rule.
In the past it wasn't possible to update any views. The main purpose of a view is to look at data, hence the name. It could also have been called a stored query.
Today, many database engines support to update views. It's bound to restrictions, some updates are virtually impossible (eg. calculated columns, group by etc).
There are two approaches:
INSTEAD OF trigger, which basically shifts the problem to the user. You write some procedural code that does the job. Certainly, no guarantees is made about correctness, consistency, etc. From RDBMS engine perspective a trigger that deletes everything from the base tables, no matter what update is made in the view, is perfectly fine.
Much more ambitious is view updates handled exclusively by RDBMS engine. Not much progress is made here: to put it mildly, if you have some good ideas there, then you can roll out PhD thesis. In practice, your favorite RDBMS might allow some limiting ad-hock view updates; check the manual:-)
Yes you can, but have a look at CREATE VIEW (Transact-SQL) and see the section Updatable Views
http://msdn.microsoft.com/en-us/library/ms187956.aspx
See Remarks\updateable view
Yes they are - the syntax is the same as updating a table
Update MyView
Set Col1 = "Testing"
Where Col2 = 3
Go
There a few conditions to creating an View that can be updated. They can be found here
EDIT:
I must add that is based on MS SQL
When a view is created in SQL Server, metadata for the referenced table columns (column name and ordinal position) is persisted in the database. Any change to the referenced base table(s) (column re-ordering, new column addition, etc) will not be reflected in the view until the view is either:
•Altered with an ALTER VIEW statement
•Recreated with DROP VIEW/CREATE VIEW statements
•Refreshed using system stored procedure sp_refreshview
Yes, using an INSTEAD OF trigger.
We generally don't update a view. A view is written to fetch data from the various tables based on joins and where conditions put.
View is just a logic put in place which gives the desired data set on invoking it.
But not sure on what scenario one needs to update a view.