use of views to protect the actual tables in sql - sql

how do views act as a mediator between the actual tables and an end user ? what's the internal process which occurs when a view is created. i mean that when a view is created on a table, then does it stands like a wall between the table and the end user or else? how do views protect the actual tables, only with the check option? but if a user inserts directly into the table then how come do i protect the actual tables?
if he/she does not use : insert into **vw** values(), but uses: insert into **table_name** values() , then how is the table protected now?

Non-materialized views are just prepackaged SQL queries. They execute the same as any derived table/inline view. Multiple references to the same view will run the query the view contains for every reference. IE:
CREATE VIEW vw_example AS
SELECT id, column, date_column FROM ITEMS
SELECT x.*, y.*
FROM vw_example x
JOIN vw_example y ON y.id = x.id
...translates into being:
SELECT x.*, y.*
FROM (SELECT id, column, date_column FROM ITEMS) x
JOIN (SELECT id, column, date_column FROM ITEMS) y ON y.id = x.id
Caching
The primary benefit is caching because the query will be identical. Queries are cached, including the execution plan, in order to make the query run faster later on because the execution plan has been generated already. Caching often requires queries to be identical to the point of case sensitivity, and expires eventually.
Predicate Pushing
Another potential benefit is that views often allow "predicate pushing", where criteria specified on the view can be pushed into the query the view represents by the optimizer. This means that the query could scan the table once, rather than scan the table in order to present the resultset to the outer/ultimate query.
SELECT x.*
FROM vw_example x
WHERE x.column = 'y'
...could be interpreted by the optimizer as:
SELECT id, column, date_column
FROM ITEMS
WHERE x.column = 'y'
The decision for predicate pushing lies solely with the optimizer. I'm unaware of any ability for a developer to force the decision, only that it really depends on the query the view uses and what additional criteria is being applied.
Commentary on Typical Use of Non-materialized Views
Sadly, it's very common to see a non-materialized SQL view used for nothing more than encapsulation to simplify writing queries -- simplification which isn't a recommended practice either. SQL is SET based, and doesn't optimize well using procedural approaches. Layering views on top of one another is also not a recommended practice.
Updateable Views
Non-materialized views are also updatable, but there are restrictions because a view can be made of numerous tables joined together. An updatable, non-materialized view will stop a user from being able to insert new records, but could update existing ones. The CHECK OPTION depends on the query used to create the view for enforcing a degree of update restriction, but it's not enough to ensure none will ever happen. This demonstrates that the only reliable means of securing against unwanted add/editing/deletion is to grant proper privileges to the user, preferably via a role.

Views do not protect tables, though they can be used in a permissions-based table-protection scheme. Views simply provide a convenient way to access tables. If you give a user access to views and not tables, then you have probably greatly restricted access.

Related

What exactly is a sql "view"

I suppose the definition might be different for different databases (I've tagged a few databases in the question), but suppose I have the following (in pseudocode):
CREATE VIEW myview FROM
SELECT * FROM mytable GROUP BY name
And then I can query the view like so:
SELECT * FROM myview WHERE name like 'bob%'
What exactly is the "view" doing in this case? Is it just a short-hand and the same as doing:
SELECT * FROM (
SELECT * FROM mytable GROUP BY name
) myview WHERE name like 'bob%'
Or does creating a view reserve storage (or memory, indexes, whatever else)? In other words, what are the internals of what happens when a view is created and accessed?
A view is a name that refers to a stored SQL query. When referenced, the definition of the query are replaced in the referencing query. It is basically the short-hand that you describe.
A view is defined by the standard and is pretty much the same thing across all databases.
A view does not permanently store data. Each time it is referenced the code is run. One caveat is that -- in some databases -- the view may be pre-compiled, so the pre-compiled code is actually included in the query plan.
By contrast, some databases support materialized views. These are very different beasts and they do store data.
Some other reasons for views:
Not everyone is a SQL expert so the Data Base Administrator might develop views consisting of complex joins on multiple tables to provide users easy access to the data they might need to access but might not know how to best do that.
On some databases you can also create read-only views. Again, a DBA might create these to limit what operations a user can perform on certain tables.
A DBA might also create a view to limit what columns of a table a user can see.

How to convert rows to columns in indexed view?

I use OUTER JOIN to get values stored in rows and show them as columns. When there is no value, I show NULL in column.
Source table:
Id|Name|Value
01|ABCG|,,,,,
01|ZXCB|.....
02|GHJK|;;;;;
View:
Id|ABCG|ZXCB|GHJK
01|,,,,|....|NULL
02|NULL|NULL|;;;;
The query looks like:
SELECT DISTINCT
b.Id,
bABCG.Value AS "ABCG"
bZXCB.Value AS "ZXCB"
bGHJK.Value AS "GHJK"
FROM
Bars b
LEFT JOIN Bars bABCG ON b.Id = bABCG.Id and b.Name = 'ABCG'
LEFT JOIN Bars bZXCB ON b.Id = bZXCB.Id and b.Name = 'ZXCB'
LEFT JOIN Bars bGHJK ON b.Id = bGHJK.Id and b.Name = 'GHJK'
I want to remove LEFT JOIN because it's not allowed in indexed view. I tried replacing it with inner SELECT, but inner SELECT is not allowed also and UNION too. I can't use INNER JOIN because I want to show NULLs in view. What should I use?
You may be able to implement something similar using an actual table to store the results, and a set of triggers against the base tables to maintain the internal data.
I believe that, under the covers, this is what SQL Server does (in spirit, if not in actual implementation) when you create an indexed view. However, by examining the rules for indexed views, it's clear that the triggers should only use the inserted and deleted tables, and should not be required to scan the base tables to perform the maintenance - otherwise, for large tables, maintaining this indexed view would impose a serious performance penalty.
As an example of the above, whilst you can easily write a trigger for insert to maintain a MAX(column) column in the view, deletion would be more problematic - if you're deleting the current max value, you'd need to scan the table to determine the new maximum. For many of the other restrictions, try writing the triggers by hand, and most times there'll come a point where you need to scan the base table.
Now, in your particular case, I believe it could be reasonably efficient for these triggers to perform the maintenance - but you need to carefully consider all of the insert/update/delete scenarios, and make sure that your triggers actually faithfully maintain this data - e.g. if you update any ids, you may need to perform a mixture of updates, inserts and deletes.
The best you are going to be able to do is use inner joins to get the matches, then union with the left joins and filter it to only return nulls. This probably won't solve your problem.
I don't know the specifics of your system but I am assuming that you are dealing with performance issues, which is why you want to use the indexed view. There are a few alternatives, but I think the following is the most appropriate.
Since you commented this is for a DW I am going to assume that your system is more intensive on reads than writes and that data is loaded into it on a schedule by an ETL process. In this kind of high read/low write* situation I would recommend you "materialize" this view, which means when the ETL process runs, to generate the table with your initial select statement that includes the left joins. You will take the hit on the write, then all your reads will be on par with the performance of the indexed view (you would be doing the same thing the indexed view would do, except in a batch instead of on a row by row basis). If your source DB and DW are on the same instance this is a better choice than an indexed view b/c it won't affect the performance of the source system (indexed views slow down inserts). This is the same concept as the indexed view because you take the performance hit on the insert to speed up the select.
I've been down this path before and come to the following conclusion:
An indexed view is more likely to be part of the solution than the entire solution.
*when I said "high read/low write" above you can also think of it as "high read/scheduled write"
SELECT DISTINCT
b.Id,
(Select bABCG.Value from Bars bABCG where b.Name = 'ABCG') AS "ABCG"
...
FROM
Bars b
you may have to add a aggregation on the value, I'm not sure how your data is organized

what is the meaning of underlying table in VIEW'S definition

am not understand ,
what is the meaning of underlying table in VIEW definition ,
A view is created by joining one or more tables. When you update record(s) in a view, it updates the records in the underlying tables that make up the view.
So, yes, you can update the data in a view providing you have the proper privileges to the underlying tables.
Think of a view as a stored query, which appears to the user as a regular table. In practical terms, there's very little difference between a view:
SELECT somefield, otherfield
FROM theview
and what's actually happening at the database level:
SELECT somefield, otherfield
FROM (
SELECT lots, of, useless,fields, somefield, otherfield
FROM underlying, tables
JOIN ...
) AS theview
Views save you from having to write the sub-query each time, so they're a time saver in that regard. However, views have the downside that depending on the underlying query, you might not able to run UPDATE/DELETE queries against the view as you could if you were directly accessing the underlying tables.
It means that the tables you select from or join against to generate the view. In this case, specifically the ones used in the fields list.

Performance when querying a View

I'm wondering if this is a bad practice or if in general this is the correct approach.
Lets say that I've created a view that combines a few attributes from a few tables.
My question, what do I need to do so I can query against this view as if it were a table without worrying about performance?
All attributes in the original tables are indexed, my concern is that the result view will have hundreds of thousands of records, which I will want to narrow down quite a bit based on user input.
What I'd like to avoid, is having multiple versions of the code that generates this view floating around with a few extra "where" conditions to facilitate the user input filtering.
For example, assume my view has this header VIEW(Name, Type, DateEntered) this may have 100,000+ rows (possibly millions). I'd like to be able to make this view in SQL Server, and then in my application write querlies like this:
SELECT Name, Type, DateEntered FROM MyView WHERE DateEntered BETWEEN #date1 and #date2;
Basically, I am denormalizing my data for a series of reports that need to be run, and I'd like to centralize where I pull the data from, maybe I'm not looking at this problem from the right angle though, so I'm open to alternative ways to attack this.
My question, what do I need to do so I can query against this view as if it were a table without worrying about performance?
SQL Server is very good in view unnesting.
Your queries will be as efficient as if the view's query were used in the query itself.
This means that
CREATE VIEW myview AS
SELECT *
FROM /* complex joins */
SELECT *
FROM mytable
JOIN myiew
ON …
and
SELECT *
FROM mytable
JOIN (
SELECT *
FROM /* complex joins */
) myview
ON …
will have the same performance.
SQL Server 2005 has indexed views - these provide indexes on views. That should help with performance. If the underlying tables already have good indexes on the queried fields, these will be used - you should only add indexed views when this is not the case.
These are known in other database systems as materialized views.
The view will make use of the index in your WHERE clause to filter the results.
Views aren't stored result sets. They're stored queries, so you'll have the performance gained from your indexes each time you query the view.
Why would it perform badly? I, mean you can think of a view as a compiled select statement. It makes use of existing indexes on the underlying tables, even when you add extra where clauses. In my opinion it is a good approach. In any case it's better than having virtually the same select statement scattered all over your application (from a design and maintainability point of view at least).
If not indexed then...
When you query a view, it's ignored. The view is expanded into the main query.
It is the same as querying the main tables directly.
What will kill you is view on top of view on top of view, in my experience.
It should, in general, perform no worse than the inline code.
Note that it is possible to make views which hide very complex processing (joins, pivots, stacked CTEs, etc), and you may never want anyone to be able to SELECT * FROM view on such a view for all time or all products or whatever. If you have standard filter criteria, you can use an inline table-valued function (effectively a parameterized view), which would require all users to supply the expected parameters.
In your case, for instance, they would always have to do:
SELECT Name, Type, DateEntered
FROM MyITVF(#date1, #date2);
To share the view logic between multiple ITVFs, you can build many inline table-valued functions on top of the view, but not give access to the underlying tables or views to users.

What SQL query shows me the tables and indexes used by a view on Informix?

What SQL query shows me the tables & indexes used by a view on Informix?
I know how to find the "original create statement" for a view in SYS_VIEWS, but that requires a human brain scanning/grokking that select. I believe I can find if the tables are indexed, once they have been identified.
Background: I need to make certain that some critical views point to current (e.g. after being "reorganized") tables. Too often I have seen views pointing to old backup tables, that were no longer indexed, and took forever to query.
I need to identify these queries regularly and "remind" the tuning DBA to rebuild the views/indexes.
The table sysdepend documents view dependencies. The columns are:
btabid - base table ID number
btype - normally T for table or V for view
dtabid - dependent table ID number
dtype - normally T for table or V for view
Consequently, for a given view with tabid N, you can write:
SELECT b.owner, b.tabname, d.*
FROM "informix".systables b, "informix".sysdepend d
WHERE d.dtabid = N
AND d.btabid = b.tabid;
If you only know the view name, then determining the view's tabid is surprisingly tricky if your database is a MODE ANSI database where you may have multiple tables with the same table name (or view name in this case) but each with a different owner. However, in the usual case (a non-ANSI database, or a unique table/view name), the query is easy enough:
SELECT b.owner, b.tabname, d.*
FROM "informix".systables b, "informix".sysdepend d
WHERE d.dtabid = (SELECT v.tabid FROM "informix".systables v
WHERE v.tabname = "viewname"
)
AND d.btabid = b.tabid;
The question asks about the indexes used by a view. Indexes are not used by a view, per se; indexes are used by the query engine when processing a query, but the indexes used could change depending on the total query - so different indexes might be used for these two queries:
SELECT * FROM SomeView;
SELECT * FROM SomeView
WHERE Column1 BETWEEN 12 AND 314;
The indexes that will be used are not recorded anywhere in the system catalog; they are redetermined dynamically when a statement is prepared.
The question also notes:
Background: I need to make certain that some critical views point to current (e.g. after being "reorganized") tables. Too often I have seen views pointing to old backup tables, that were no longer indexed, and took forever to query.
How do you do your reorganization? Do you create a new table with the desired structure, copy the data from old to new, then rename old, rename new? That probably would be the explanation - the table renaming reworks the views that reference the table. What form of reorganization are you doing? Can you use a different technique? A classic standby is to use ALTER INDEX indexname TO CLUSTER (after altering it to NOT CLUSTER if it was already clustered). This rebuilds the table and the indexes - without the views breaking. Alternatively, you can consider an ALTER FRAGMENT operation.
It also seems a bit odd to keep the old tables around. That suggests that your reorganization is more a question of dropping old data. Maybe you should fragment your table by date ranges, so that you detach a fragment when it has reached its 'end of useful life' date. Dropping the tables would also drop the views that depend on it, ensuring that you rebuild the views with the new table names.
Another alternative, therefore, is to simply ensure that the reorganization drops and recreates the views.
I need to identify these queries regularly and "remind" the tuning DBA to rebuild the views/indexes.
Worrisome...it should just be part of the standard procedure for completing the reorganization. Basically, you have a bug to report in that procedure - it does not ensure that the views are fully operational.