update granted on view, but cannot update underlying table, why? - sql-server

I have a table and a view. They are in different schema, but have the same owner:
according to sys.objects: principal_ID = null, schema_ID is 1 and 4
according to sys.schemas: both schemas have the same principal_id (1 = dbo)
The view is simply select a,b,c from table
Now a user has been given the right to select, insert, update and delete rows from the view. He has no rights on the underlying table.
In fact, the user can select data. But if he wants to change anything, we get two errors: 'No SELECT granted on table" and "No UPDATE granted on table".
What is going wrong here?

Update-able views are only update-able if you grant the permissions on the table, too:
Requires UPDATE, INSERT, or DELETE permissions on the target table, depending on the action being performed.
See the TechNet article Modify Data Through a View.

The solution was that I was accessing the view with the C# SqlCommandBuilder class. But what I did not know is that the CommandBuilder tries to be "intelligent" and analyzes the view. It then creates statements which access the underlying tables, instead of the view. The only solution is to circumvent the SqlCommandBuilder.
I stumbled over the problem also this year, here is another link:
https://stackoverflow.com/a/31231563/2504785

Related

SQL Server: Best way to automatically stream updates to a summary table based on changes from another table

I am currently working in a SQL server database where I have a table User that has a schema like so:
username
category
user1
gaming
user2
gaming
user3
sports
My summary table UserCategoryCount is a simple groupby statement for how many users belong to each category and looks like this:
category
numUsers
gaming
2
sports
1
New entries are constantly being uploaded to the User, and I want to be able to stream updates in the User table to the UserCategoryCount summary table. I am aware that I can create a simple VIEW statement that performs a groupby on the User table, but I would like UserCategoryCount to be its own table that automatically changes based on new users being uploaded to the User table.
My first thought was to create a trigger that will detect when the User table has been updated. So far, the most simple but cheesy solution I can think of is creating a trigger that simply deletes and refreshes UserCategoryCount:
CREATE TRIGGER TRG_Add_User
ON User
AS
BEGIN
DELETE FROM UserCategoryCount
INSERT INTO UserCategoryCount (category, numUsers)
SELECT Category, Count(Category) as numUsers
FROM User GROUP BY Category
END
GO
But this seems like a really hacky way of updating the UserCategoryCount table. Any help on how to improve this update statement so that I don't have to completely overwrite the table every time a new user or batch of users has been inserted would be greatly appreciated.
For a start, your trigger is seriously flawed: it does not use the inserted or deleted tables and instead recalculates the whole thing every time, this is going to be very bad for performance. It also does not specify whether it is for inserts, updates or deletes.
A much better solution is to use an indexed view. This is like a regular view, except that the server maintains the actual data on disk, and updates it in real-time whenever there are changes to the underlying tables.
CREATE OR ALTER VIEW dbo.UserCategoryCount
WITH SCHEMABINDING
AS
SELECT
u.Category,
COUNT_BIG(*) AS numUsers
FROM dbo.User u
GROUP BY u.Category;
GO
CREATE UNIQUE CLUSTERED INDEX CX_UserCategoryCount ON dbo.UserCategoryCount (Category);
There are some restrictions on indexed views, among them:
They must be schema-bound, and therefore underlying columns cannot be changed
All tables must be two-part, schema and table
Only joins allowed are INNER or CROSS, no LEFT/RIGHT/FULL/APPLY or derived tables, CTEs or subqueries.
If there is a GROUP BY, you must add COUNT_BIG, and the only other aggregate allowed is SUM

Is it possible to protect columns of a view in snowflake?

I'm working at a company where one team manages the databases and others use tables / views from there. From time to time, views get refactored which might break things for other teams.
Is it possible to protect some columns so that those cannot simply be renamed / dropped? Or at least have a log message telling the person who wants to do it that another team depends on it?
In Snowflake, only users with roles who have privileges to update a view by changing its definition are able to make changes on the specified view. If a specific role has privileges to replace view definition, there is no mechanism to stop them from renaming or dropping columns.
You can see the logs in QUERY_HISTORY function in Snowflake Information_schema. The functions gives extensive information on which user ran the query and the time it ran. A query like below would bring the appropriate information:
select user_name, role_name, query_text, start_time, end_time from table(information_schema.query_history())
where query_text ilike '%replace view %'
order by start_time desc;
The privilege to alter a view is all or nothing. It does not restrict which columns the role can or cannot alter, remove, add, etc. However, since Snowflake allows using views as part of another view, this can form part of your organization's overall approach to do what you're seeking.
For example, create a base view that has all the protected columns. Tightly control access to which roles can alter the base view. From the base view, create views on top that less privileged roles can alter.

SQL Server - Are permissions on tables required?

My question again to be more specific:
How can I modify data through a view and don't have to grant SELECT-Permissions on the table?
I am designing and developing a new database at the company i am working for.
The business rules say, that users are allowed to access specific rows in tables only.
So I use views to check the permissions of the user and return only those records, the user has access to.
So far so god.
But, I have to check the permissions also on INSERT and UPDATE and DELETE with INSTEAD-of-Triggers. Because the rows a User can SELECT may not be those, he can modify.
My problem is:
When I have an view and grant SELECT, INSERT, UPDATE and DELETE Permissions, it doesn't work. When I insert into this view, SQL Server wants INSERT-Permission at the base table. That wouldn't be a problem. But when I update or delete rows through the view, SQL Server wants SELECT and UPDATE/DELETE permissions granted on the base table.
I don't want to give SELECT-rights on the table.
Thanks
Chris
I'm thinking at:
1/ Restrict VIEW rows by adding in its definition a condition like this:
WHERE UserName = SUSER_SNAME()
or
WHERE UserName = CURRENT_USER()
or
2/ Using INSTEAD OF triggers on the involved view.
P.S. Indeed, CREATE VIEW WITH EXECUTE is not allowed. Thank you for your messages.

Why we can edit view in sql server

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

inserting into a view in SQL server

I have a SQL Server as backend and use ms access as frontend.
I have two tables (persons and managers), manager is derived from persons (a 1:1 relation), thus i created a view managersFull which is basically a:
SELECT *
FROM `managers` `m`
INNER JOIN `persons` `p`
ON `m`.`id` = `p`.`id`
id in persons is autoincrementing and the primary key, id in managers is the primary key and a foreign key, referencing persons.id
now i want to be able to insert a new dataset with a form in ms access, but i can’t get it to work. no error message, no status line, nothing. the new rows aren’t inserted, and i have to press escape to cancel my changes to get back to design view in ms access.
i’m talking about a managers form and i want to be able to enter manager AND person information at the same time in a single form
my question is now: is it possible what i want to do here? if not, is there a “simple” workaround using after insert triggers or some lines of vba code?
thanks in advance
The problem is that your view is across several tables. If you access multiple tables you could update or insert in only one of them.
Please also check the MSDN for more detailed information on restrictions and on proper strategies for view updates
Assuming ODBC, some things to consider:
make sure you have a timestamp field in the person table, and that it is returned in your managers view. You also probably need the real PK of the person table in the manager view (I'm assuming your view takes the FK used for the self-join and aliases it as the ID field -- I wouldn't do that myself, as it is confusing. Instead, I'd use the real foreign key name in the managers view, and let the PK stand on its own with its real name).
try the Jet/ACE-specific DISTINCTROW predicate in your recordsource. With Jet/ACE back ends, this often makes it possible to insert into both tables when it's otherwise impossible. I don't know for certain if Jet will be smart enough to tell SQL Server to do the right thing, though.
if neither of those things works, change your form to use a recordsource based on your person table, and use a combo box based on the managers view as the control with which you edit the record to relate the person to a manager.
Ilya Kochetov pointed out that you can only update one table, but the work-around would be to apply the updates to the fields on one table and then the other. This solution assumes that the only access you have to these two tables is through this view and that you are not allowed to create a stored procedure to take care of this.
To model and maintain two related tables in access you don’t use a query or view that is a join of both tables. What you do is use a main form, and drop in a sub-form that is based on the child table. If the link master and child setting in the sub-form is set correctly, then you not need to write any code and access will insert the person’s id in the link field.
So, don’t use a joined table here. Simply use a form + sub-form setup and you be able to edit and maintain the data and the data in the related child table.
This means you base the form on the table, and not a view. And you base the sub-form on the child table. So, don't use a view here.

Resources