I have an application that allows users to define their own views in SQL and later have the application generate metadata about that view. This is mostly really easy as information_schema.columns tells me what the columns/types the view uses.
However, is there a way to find out whether the view can accept INSERT or UPDATE queries without doing something horrible like parsing the SQL myself or doing a test INSERT and checking for errors/rolling back the transaction?
I'm assuming SQL Server here, YMMV with other RDBMS products...
Assuming you're not using INSTEAD OF triggers, there is no flag or query that indicates whether a view is updatable or not, probably because a view can be updatable for certain classes of updates but not others.
Per the documentation:
Updatable Views
You can modify the data of an underlying base table
through a view, as long as the following conditions are true:
Any modifications, including UPDATE, INSERT, and DELETE statements, must reference columns from only one base table.
The columns being modified in the view must directly reference the underlying data in the table columns.
The columns cannot be derived in any other way, such as through the following: An aggregate function: AVG, COUNT, SUM, MIN, MAX,
GROUPING, STDEV, STDEVP, VAR, and VARP.
The column cannot be computed from an expression that uses other columns. Columns that are formed by using the set operators UNION,
UNION ALL, CROSS JOIN, EXCEPT, and INTERSECT amount to a
computation and are also not updatable.
The columns being modified are not affected by GROUP BY, HAVING, or DISTINCT clauses.
TOP is not used anywhere in the select_statement of the view together with the WITH CHECK OPTION clause.
The previous restrictions apply to any subqueries in the FROM
clause of the view, just as they apply to the view itself. Generally,
the Database Engine must be able to unambiguously trace modifications
from the view definition to one base table. For more information, see
Modify Data Through a View.
So you might have a view that is based off a JOIN, where certain updates (involving only one base table) were legal, while others (involving multiple base tables) were not.
Related
I have a StockinHand view generated from stock_Outward & Stock_Inward tables right now needs the sorting based on frequency i.e most moving stock items should be on top of the table
My tables are like below:
tbl_StockInward:
ID, Stock_Code,Units,Rate, Description, Vendor, DateOfPurchase, DateOfUpdate, Purchased_By, WareHouse, Remarks,
vice versa tbl_StockOutward
Please help me
Thanks in advance
Just like in sub queries, you can't use ORDER BY in a view definition in sql server unless you also use TOP.
The reason for this is that Views are acted upon as if they where tables, and tables in sql server (in fact, in any relational database) are considered as not ordered sets.
Just like there is no meaning to the order of records stored in a table, there is also no meaning to the order of records fetched by a view.
You can use a dirty hack and write SELECT TOP 100 PERCENT ... and then use ORDER BY, but I doubt if it has any meaning at all.
Having said all that, you can of course use ORDER BY in any query that selects from a view.
In sql server we can Update data view.I think the concept of view is a read only table.
Why we can edit view in sql.is there possible in oracle?
To answer your question of why can we create an editable view, it is so that you can limit access to fields that you do not want updated (or viewed). Then you can give a user access to the view, but not to the underlying tables
For a simple example, you could have a personnel table. You could create an view allowing some users to update a field like emergency contact details, but not see or update bank details or salary
There are lots of criteria to meet to make a view updatable, and you can indeed use INSTEAD OF triggers for extended functionality http://msdn.microsoft.com/en-us/library/ms187956.aspx
I think the concept of view is a read only table
No, it's more of a virtual table - anywhere you have a real table, you ought to be able to replace it with a view, and the users should be none the wiser.
According to Codd:
Rule 6: The view updating rule:
All views that are theoretically updatable must be updatable by the system.
However, in practicality, this ideal has not been achievable.
In addition to what #JamieA wrote, views can not only limit access to fields, but also limit access to data in the table.
Look at simple SQL-Fiddle example and experiment with it.
The view in the example restrict access only to columns id,val1 of the table, but also restrics access to rows (only id = 2..10). You can update and delete only rows 2..10 throught the view.
However the view does not prevent insertion of a row with id = 20
Here is another example - a view with check option - it this case the view prevents not only deletes and updates, but prevent also inserting rows that do not match a where clause of the view.
#yogi wrote that we can't update a view if the view joins two tables -> here is a third demo that shows a simple view that joins two tables, and how an update of this view works.
These simple examples are for Oracle, but after small modifications should also work in MS-SQL (must change datatypes in create tables), since when i looked througs MSDN documentation (section: updatable views -> http://msdn.microsoft.com/en-us/library/ms187956.aspx), I didn't find any significant differences between ms-sql and oracle, it seems that views work similary on both databases.
Yes it is possible in Oracle, the other answers already explained why views are updatable and had shed some light on that question, they are also allowed in Oracle but have some restrictions/limitations here is the Oracle documentation
Like, the view select cant have: aggregate functions, distinct clause, group by... read the link for more info
Since views are read only tables and its doesn't support DML statements you can't perform update on view.
An interesting factor is there you can write update statemnt over view and write a instead of trigger for that hence you can perform multiple update statements on tables which are in the view.
According to Pinal Dev Views having following limitations
ORDER BY Does Not Work.
Adding Column is Expensive by Joining Table Outside View
Index Created on View not Used Often
SELECT * and Adding Column Issue in View
COUNT(*) Not Allowed but COUNT_BIG(*) Allowed
UNION Not Allowed but OR Allowed in Index View
Cross Database Queries Not Allowed in Indexed View
Outer Join Not Allowed in Indexed Views
SELF JOIN Not Allowed in Indexed View
Keywords View Definition Must Not Contain for Indexed View
View Over the View Not Possible with Index View
I'm having issues creating an index on a view that uses a custom CLR aggregate function.
I don't see any way to flag the aggregate function as deterministic or with schemabinding.
I'm creating my function like so:
CREATE ASSEMBLY StringUtil
AUTHORIZATION dbo
FROM 'C:\StringUtil.dll'
WITH PERMISSION_SET = UNSAFE
GO
CREATE AGGREGATE SUMSTRING (#input nvarchar(200))
RETURNS nvarchar(max) WITH SCHEMABINDING
EXTERNAL NAME StringUtil.Concatenate
And my view is defined as:
CREATE VIEW RolledValues WITH SCHEMABINDING
AS
SELECT ID, SumString(ValueText) as Value FROM [dbo].[IDValue]
GROUP BY ID
The issue occurs when I try to create an index on that view:
CREATE UNIQUE CLUSTERED INDEX IDX_RollValues_ID_VALUE on RolledValues (ID)
Error: Cannot create index on view "dbo.RolledValues" because it uses aggregate
"dbo.SumString". Consider eliminating the aggregate, not indexing the view, or
using alternate aggregates.
So is it possible to use a custom aggregate function in an indexed view? I cannot find any documentation on this...
The page on Creating Indexed Views lists a number of restrictions:
The SELECT statement in the view cannot contain the following Transact-SQL syntax elements:
...
A CLR user-defined aggregate function.
There's not even provision, at the current time, to describe a CLR aggregate as Deterministic (at least, if the API was going to be consistent). The SqlFunctionAttribute has an IsDeterministic property. No such property exists in SqlUserDefinedAggregateAttribute
It does help to reason about things if you consider why so many restrictions exist on indexed views.
The ones on aggregates have a pretty simple explanation - you're only allowed to use aggregates (such as SUM and COUNT_BIG) that have the property that SQL Server will be able to adjust the values, or add or remove rows from the index, based purely on the subset of rows that are the subject of the current transaction.
E.g. if the view has a row with ID=19, COUNT_BIG=5, and SUM=96, and a transaction deletes 3 rows with ID 19, whose SUM adds to 43, then it can update that row of the view to be COUNT_BIG=2 and SUM=53. Alternatively, if the transaction had deleted 5 rows with ID=19, it would have caused the row to be removed.
Note that in either case, we don't have to examine any other rows of the table to determine if they have ID=19.
So how could SQL Server hope to achieve similar functionality with a user defined aggregate? The current interface for user defined aggregates doesn't have the sort of support you'd need (it would need to have a trigger like interface also).
I know in SQL Server you can create indexes on a view, then the view saves the data from the underlying table. Then you can query the view. But, why I need to use view instead of table?
You may want to use a view to simplify on queries. In our projects, the consensus is on using views for interfaces, and especially "report interfaces".
Imagine you've got a client table, and the manager wants a report every morning with the client's name, and their account balance (or whatever). If you code your report against the table, you're creating a strong link between your report and your table, making later changes difficult.
On the other hand if your report hits a view, you can twist the database freely; as long as the view is the same the report works, the manager is happy and you're free to experiment with the database. You want to separate client metadata from the main client table? go for it, and join the two tables in the view. You want to denormalize the cart info for the client? no problem, the view can adapt...
To be honest, it's my view as a programmer but other uses will certainly be found by db gurus :)
One advantage of using an indexed view is for ordering results of 2 or more columns, where the columns are in different tables. ie, have a view which is the result of table1 and table2 sorted by table1.column1, table2.column2. You could then create an index on column1, column2 to optimise that query
A table is where the data is physically stored.
A view is where tables are summarized or grouped to make groups of tables easier to use.
An indexed view allows a query to use a view, and not need to get data from the underlying table, as the view already has the data, thus increasing performance.
You could not achieve the same result with just tables, without denormalizing your database, and thus potentially creating other issues.
Basically, use a view:
When you use the same complex query on many tables, multiple times.
When new system need to read old table data, but doesn't watch to change their perceived schema.
Indexed Views can improve performance by creating more specific index without increasing redundancy.
A view is simply a SELECT statement that has been given a name and stored in a database. The main advantage of a view is that once it's created, it acts like a table for any other SELECT statements that you want to write.
The select statement for the view can reference tables, other views and functions.
You can create an index on the view (indexed view) to improve performance. An indexed view is self-updating, immediately reflecting changes to the underlying tables.
If your indexed view only selects columns from one table, you could just as well place the index on that table and query that table directly, the view would only cause overhead for your database. However, if your SELECT statement covers multiple tables with joins etc. than you could gain a performance boost by placing an index on the view.
Huge database in mssql2005 with big codebase depending on the structure of this database.
I have about 10 similar tables they all contain either the file name or the full path to the file. The full path is always dependent on the item id so it doesn't make sense to store it in the database. Getting useful data out of these tables goes a little like this:
SELECT a.item_id
, a.filename
FROM (
SELECT id_item AS item_id
, path AS filename
FROM xMedia
UNION ALL
-- media_path has a different collation
SELECT item_id AS item_id
, (media_path COLLATE SQL_Latin1_General_CP1_CI_AS) AS filename
FROM yMedia
UNION ALL
-- fullPath contains more than just the filename
SELECT itemId AS item_id
, RIGHT(fullPath, CHARINDEX('/', REVERSE(fullPath))-1) AS filename
FROM zMedia
-- real database has over 10 of these tables
) a
I'd like to create a single view of all these tables so that new code using this data-disaster doesn't need to know about all the different media tables. I'd also like use this view for insert and update statements. Obviously old code would still rely on the tables to be up to date.
After reading the msdn page about creating views in mssql2005 I don't think a view with SCHEMABINDING would be enough.
How would I create such an updateable view?
Is this the right way to go?
Scroll down on the page you linked and you'll see a paragraph about updatable views. You can not update a view based on unions, amongst other limitations. The logic behind this is probably simple, how should Sql Server decide on what source table/view should receive the update/insert?
You can modify partitioned views, provided they satisfy certain conditions.
These conditions include having a partitioning column as a part of the primary key on each table, and having a set on non-overlapping check constraints for the partitioning column.
This seems to be not your case.
In your case, you may do either of the following:
Recreate you tables as views (with computed columns) for your legacy soft to work, and refer to the whole table from the new soft
Use INSTEAD OF triggers to update the tables.
If a view is based on multiple base tables, UPDATE statement on the view may or may not work depending on the UPDATE statement. If the UPDATE statement affects multiple base tables, SQL server throws an error. Whereas, if the UPDATE affects only one base table in the view then the UPDATE will work (Not correctly always). The insert and delete statements will always fail.
INSTEAD OF Triggers, are used to correctly UPDATE, INSERT and DELETE from a view that is based on multiple base tables. The following links has examples along with a video tutorial on the same.
INSTEAD OF INSERT Trigger
INSTEAD OF UPDATE Trigger
INSTEAD OF DELETE Trigger