How to ALTER a view in PostgreSQL - sql

PostgreSQL does not allow altering a view (i.e. adding column, changing column orders, adding criterie etc.) if it has dependent objects. This is really getting annoying since you have to write a script to:
Drop all the dependent objects,
Alter the view,
Recreate all the dependent objects back again.
I understand that postgreSQL developers have very reasonable concerns to prevent altering views. But do you guys have any scripts/shot-cuts to do all those manual stuff in a single run?

Adding new columns isn't a problem, changing datatypes or changing the order of the columns, that's where you get problems.
Don't change the order, it's not
that important anyway, just change your query:
SELECT a, b FROM view_name;
SELECT b, a FROM view_name;
When you have to change a datatype
of a column, you have to check the
depend objects as well. These might
have problems with this new
datatype. Just get the definition of
this object and recreate after the
changes. The information_schema and
pg_catalog help you out.
Make all changes within a single
transaction.

If I place a addtional "drop view xyz; commit;" before the "create or replace view xyz as ..." statement, at least in many cases I resolve the blocking problem described above.

Related

How to automatically update a content of table after an insert update or delete

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.

SQL Server, VIEW has mixed up data

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.

Are there any shortcuts for creating a table variable to match the columns in a view?

I frequently need to create table variables within procedures, to store the top 25 rows from a view for processing.
I need to store these small batches in variables temporarily, because I'm performing numerous operations that modify data within the underlying tables, and some of these operations cause the rows to no longer appear within the view itself based on the view criteria (this is by design).
I need to keep the data around for the entire processing session, and I can't rely on the view itself to remain consistent through the operation.
The problem is, since we're doing this in many instances across multiple databases, if we ever make any changes to the columns in any of our views, the code becomes somewhat bug-prone since we also have to make sure to modify the relevant table types as well - without making any typos or mistakes, or overlooking anything.
So my question is, can we just declare table variables (or table types, if necessary) by just stating "Match the current columns in this view?"
That would make things much easier, since it would automatically keep all relevant table variables in sync with the current layout of the views in question, and eliminate the headache that comes with trying to keep it all straight manually.
If no such shortcut exists, then I guess we'll just have to create custom table types matching our views as needed, to at least keep it as centralized as possible.
If the usage of type variable could be replaced by Temporary Table something like:
SELECT * INTO #TempTable FROM myView
Will do the job perfectly.
With SELECT INTO, the table will be created with colomn and metadata avialable in you select statement.
Hope this helps.

Is a view in the database updatable?

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.

Database VIEW does not reflect the data in the underying TABLE

Input:
The customer claims that the application (.NET) when querying for some data returns data different from when the customer looks into the data table directly.
I understand there could be various reasons and in completely different places. My purpose is not to solve it here, but rather to ask experienced DBAs and DB developers if:
Is it possible for a VIEW to show data that does not match the underlying TABLE(s)?
What are possible causes/reasons for this?
Can an UPDATE statement on a view cause future SELECTs to return 'updated' data, when the table really does not?
Possible causes (please comment on those with question-marks):
the reason is that there are two separate transactions, which would explain the customers' confusion.
the underlying table was altered, but the view was not refreshed (using sp_refreshview)
a different user is connecting and can see different data due to permissions ?
programmer error: wrong tables/columns, wrong filters (all-in-one here)
corruption occurs: DBCC CHECKDB should help
can SELECT ... FOR UPDATE cause this ???
? __
What really happened (THE ANSWER):
Column positions were altered in some tables: Apparently the customer gave full database access to a consultant for database usage analysis. That great guy changed the order of the columns to see the few audit fields at the beginning of the table when using SELECT * ... clauses.
Using dbGhost the database schema was compared to the schema of the backup taken few days before the problem appeared, and the column position differences were discovered.
What came next was nothing related to programming, but more an issue of politics.
Therefore the sp_refreshview was the solution. I just took one step more to find who caused the problem. Thank you all.
Yes, sort of.
Possible Causes:
The View needs to be refreshed or recompiled. Happens when source column definitions change and the View (or something it depends on) is using "*", can be nasty. Call sp_RefreshView. Can also happen because of views or functions (data sources) that it calls as well.
The View is looking at something different from what they/you think. They are looking at the wrong table or view.
The View is transforming the data in an unexpected way. It works right, just not like they expected.
The View is returning a different subset of the data than expected. Again, it works right, just not like they think.
They are looking at the wrong database/server or with a Logon/user identity that causes the View to alter what it shows. Particularly nefarious because unlike Management Studio, most client programs do not tell you what database/server they are pointed at.
it is possible if the underlying table has been changed and sp_refreshview has not been ran against the view, so the view will have missing columns if those were added to the table.
To see what I mean read how to make sure that the view will have the underlying table changes by using sp_refreshview
You can create views with locking hints which would mean you might be getting a dirty read. Or alternatively when they access the table directly, they might be using locking hints which could be giving them a dirty read at that point.
Another possibility that users don't seem to understand is that the data is fluid. The data you read at 3:00 in a view may not be the same data that you see at 3:30 looking directly at the table becasue there have been changes in the meantime.
A few possibilities:
Your .NET application may not be pointing to where you or they think it is pointing. For example, it's pointed to a test server by mistake
If the view has an index on a float or numeric value, the value may appear different from the underlying query due to rounding
The ANSI_NULLS setting is specific to the view when it was created. If it's different from the setting during the select(s) on the underlying tables it could cause discrepancies for certain kinds of queries
The underlying table structures have changed and the view hasn't been refreshed (especially a problem if it uses "SELECT *")
I'll edit this post if I think of any others.
EDIT: Here's an example of how the ANSI_NULLS setting can throw off your results:
SET ANSI_NULLS ON
DECLARE
#i INT,
#j INT
SET #i = NULL
SET #j = 1
SELECT
CASE WHEN #i <> #j THEN 'Not Equal' ELSE 'Equal' END
SET ANSI_NULLS OFF
SELECT
CASE WHEN #i <> #j THEN 'Not Equal' ELSE 'Equal' END
The results which you should receive are:
Equal
Not Equal
Assuming the view does not actually transform the data, technically it is possible if a corruption occurs. View retrieves data from one index, 'table' retrieves from another (ie. from clustered) and the two are out of sync. A DBCC CHECKDB should reveal the problem.
But human error is much more likely, ie. they are looking at different table than the view, or at different records.
For sure there are other things:
1) Derived attributes are pulling from wrong tables in the view
2) The view is using incorrect tables
3) incorrect or missing joins in the view
to name a few