How to determine which table of a multitable view are updatable? - sql-server

Update: My problem doesn't seem to be with the SQL server. I executed an update statement inside the database manually against the view and I was able to update the Bar table. I'll close this and research the OleDbDataAdapters more since I think the problem lies with them.
This question applies to MS SQL Server 2000. How do I determine which table of the multitable view can be modified?
I have the following view:
CREATE VIEW dbo.MyView
AS
SELECT dbo.Foo.Id, dbo.Bar.Id, dbo.Foo.column1, dbo.Foo.column2,
dbo.Foo.column3, dbo.Bar.column1, dbo.Bar.column2,
dbo.Bar.column3
FROM dbo.Bar INNER JOIN
dbo.Foo ON dbo.Bar.Id = dbo.Foo.ForeignId
When I update this view, (using VB.NET OleDbDataAdapters), I can update columns of Foo, but not columns of Bar. My investigation into this tells me that in a multitable view like this that MS SQL server only allows you to update one of the tables. So my question is, how does SQL server determine which table can be updated?
I tried a test where I edit the fields of a particular row from the view. Afterwards, I used the OleDbDataAdapter to update the view. Only the edits to the Foo table were accepted. The edits to the Bar table were ignored (no exception thrown).
Is there a way to predict which of the tables can be updated or a way to control which one? What if I wanted Bar to be the updateable table instead of Foo?
Update: I found this on google, MS SQL Server 2000 Unleased:
http://books.google.com/books?id=G2YqBS9CQ0AC&pg=RA1-PA713&lpg=RA1-PA713&dq=ms+sql+server+"multitable+view"++updated&source=bl&ots=ZuQXIlEPbO&sig=JbgdDe5yU73aSkxh-SLDdtMYZDs&hl=en&ei=b-0SSq-aHZOitgPB38zgDQ&sa=X&oi=book_result&ct=result&resnum=1#PRA1-PA713,M1
(For some reason the URL I'm trying to paste doesn't work with this site, sorry that you have to copy&paste.)
Which says:
An update through a multitable view cannot affect more than one underlying base table.
A delete cannot be executed against multitable views.
But, I don't yet see an answer to my question.
Again, my question is:
How do I determine which table of the multitable view can be modified?
I realize I can write two update statements one for each table. My concern is different. I need to audit code that uses views like the one above and does updates on the views. I was hoping to find a way to determine which parts of the updates will be silently ignored.
Example:
I edit Bar.Column1 and then call the Update() method of the OleDbDataAdapter. This results in the Bar table not being modified nor is an exception thrown. If I edit Foo.Column2 then call Update() the Foo table does get modified.

You can update any table in the view, but only fields that are all in the same table in that statement. If you need to update fields from two tables in a view, then you must write two update statements.
Personally I prefer not to update or delete from views at all. I use the base tables for that.
There are also rules concerning whether view is updateble. See Books online. Search for this:
views-SQL Server, modifying data

You need to be able to uniquely identify the row in the table by returning the primary key. Try returning dbo.Bar.Id in the view, and you should be able to edit columns in table Bar.

Related

How to edit records in SQL-Server stored procedure

I would like to know the secret of how SQL statements in SQL-Server go from being read-only to editable. Right click on any table, and the interface gives the option of "Selecting" or "Editing" records. Is there a property in the SQL statement that designates the recordset as editable or read-only?
I will use the simplest possible example: I have designed a table with two fields: an integer field, designated as an identity and a unique index. The second is an nvarchar, designed for manual editing. Writing a query window, I write a SQL statement for the table, and I am not able to edit the text field. Also, Stored procedures, which I favor because I can evoke them with the greatest effeciency, also renders an uneditable recordset. The only way I have found to succeed is in SSMS, when choosing the edit feature on a table.
I use Microsoft Access extensively, and all the tables that Access hosts are linked to SQL-Server tables. When I use the Microsoft Access JET engine to write queries on these same tables, I can edit the recordsets the queries generate, but not when I use pass-through queries to evoke the same contents in a table function or stored procedure. With no table joins, no calculated fields, nor anything else that would impose a known reason for me not to be able to edit the recordsets, the inability poses a barrier to producing some of my deliverables.
Thanks, in advance, for your support. Here are quick examples:
Select
IDField
, TextField
From
SampTable
Create Procedure TestProc
AS
BEGIN
Select
IDField
, TextField
From
SampTable
END
Create FUNCTION [dbo].[TestFunction]()
RETURNS TABLE
AS
RETURN
(
Select
IDField
, TextField
From
SampTable
)
SQL Server is not the same kind of thing as MS Access. MS access is a combination of front-end and back end at the same time, which is nice and easy for users, and does have its place. It's like a souped up version of excel with some very limited multi user functionality. But with SQL Server, the expectation is that you are splitting the responsibilities between front end and back end.
Yes, SSMS does provide the ability to right click a table (or a view referencing one table) and "edit top 200 rows". Honestly, I wish it didn't. It shouldn't.
If you have an access "front end" using linked tables in SQL Server in the "back end", that's similar functionality. And yeah, there are some limited uses cases where that's an appropriate sort of solution, ideally as a temporary thing. But really, if you're putting data into SQL Server, the expectation is that you're building some kind of "real" user interface, which uses DML statements constructed by the application, or stored procedure execution, or some kind of ORM and DBContext, to modify the data. Even in MS Access, you should switch from direct table editing to forms.
The reason why you can't edit the results of a stored procedure or function is that the output of those objects is just a temporary copy of the data. It's not the "actual data in the tables". And, if you think about it, how could it be? For example, imagine if I wrote a stored procedure like this:
create table t (i int primary key, j int);
create procedure p as begin
select total_j = sum(j) from t;
end
When I run that stored procedure I'm going to get a single value which is the sum of j across all rows. How could I edit this value? If I changed it from, say, 100 to 200, what does that mean in terms of the contents of column j in the table? Do I add 100 to some arbitrary row? Do I add 1 to each of the first 100 rows in order of the primary key? The concept becomes incoherent.
I know what you're thinking: "But what if my stored procedure doesn't aggregate? Surely then the data that comes back can really just be a "pointer" to the data in the table, not a copy?". And yeah, in principle that could be true. But think about the implications of that. While you're looking at the results, can anyone else change the underlying data in the table? Can you both change it at the same time? Who decides how to resolve that problem - the SQL engine? Can someone else drop the table while you are editing data? And so on and so forth.
It's the wrong way to think about SQL Server (or any "real" database engine). The data you see as the result of a select is read from the tables, and sent over the network to the client as your own personal copy. It is no longer connected to the tables it came from.
Oh... and in case you're wondering how you can edit the data "directly in the tables" if you're using linked tables in MS Access: you still can't. Access does some work under the covers for you. To prove this, try linking a SQL Server table to MS Access, then pulling up the row in access, and starting to edit it. Then, before finishing your edit, go in to SSMS and update the row you are editing in access. Then try to save your changes in Access.

Using triggers to maintain data integrity from similar tables in two databases

I have two SQL Server databases.
One is being used as the back-end for a Ruby-On-Rails system that we are transitioning from but is still in use because of the Ruby apps we are rewriting in ASP.NET MVC.
The databases have similar tables, but not identical, for the Users, Roles and Roles-Users tables.
I want to create some type of trigger to update the user and roles-users tables on each database when a modification is made on the other database of the same table.
I can't just use the users table on the original database because Ruby has a different hash function for the passwords, but I want to ensure that changes on one system are reflected on the other instanter.
I also want to avoid the obvious problem that an update on the one database triggers an update on the other which triggers an update on the first and the process repeats itself until the server crashes or something similarly undesirable happens or a deadlock occurs.
I do not want to use database replication.
Is there a somewhat simple way to do this on a transaction per transaction basis?
EDIT
The trigger would be conceptually something like this:
USE Original;
GO
CREATE TRIGGER dbo.user_update
ON dbo.user WITH EXECUTE AS [cross table user identity]
AFTER UPDATE
AS
BEGIN
UPDATE Another.dbo.users SET column1=value1, etc., WHERE inserted.ID = Another.dbo.users.ID;
END
The problem I am trying to avoid is a recursive call.
Another.dbo.users will have a similar trigger in place on it because the two databases have different types of applications, Ruby-On-Rails on the one and ASP.NET MVC on the other that may be working on data that should be the same on the two databases.
I would add a field to both tables if possible. When adding or updating a table the 'check' field would be set to 0. The trigger would look at this field and if it is 0, having been generated by an application event, then the trigger fires the insert/update into the second table but the check field would have a 1 instead of 0.
So when the trigger fires on the second table it will skip the insert back into table one.
This will solve the recursive problem.
If for some reason you can not add the check field, you can use a separate table with the primary key to the table and the check field. This need more coding but would work also.

Modifying view data in T-SQL

My company uses Microsoft SQL Server Management Studio and T-SQL for its database functionalities. One the daily activities my team performs is updating the data in a view that contains around 4k-5k records.
Let's suppose the view has 10 fields. So our job is to change the value of field_5, considering the values of field_1, field_2 and field_7. We have always been doing it manually and it takes close to 2-3 hours to go through all 5k records and check all the fields' values and update the required field.
I thought of automating the task and build a script for it but I can't seem to find anything on MSDN. The closest I got was this - https://msdn.microsoft.com/en-us/library/ms178076.aspx. But it talks about altering the structure of the view, not updating the data inside the view while retaining structure. Further googling also didn't help much.
Is there any way to do this?
What's the definition of the view? Does it meet the criteria for an updatable view? If so you just need an update statement.
A trivial example would be
UPDATE YourView
SET Field5 = Field1+Field2+Field7
Otherwise if it does not meet the requirements you could write an instead of trigger implementing the desired logic and still use an update statement.
Ok, you use the word 'View' but I assume you mean a 'Table'? Views are dynamic and (apart from indexed views) don't actually store data, they store queries that run a certain set of code when you call the view.
Assuming you're talking about a table, you're looking for something like below;
UPDATE table
SET field_5 = (field_1 + field_2 + field_7)
That will change field_5 in every row to match your calculation.

DBMS: How to get the creation date of a column in SQL Server [duplicate]

This question already has answers here:
Find the date/time a table's column was created
(7 answers)
Closed 8 years ago.
Example:
If a column got added in the table much after the table was created.
Where does the Data/Time information of it gets stored?
SQL Server still does not have any system views that allow you to see the create/modify date at a column level. You will have to see the modify_date column of a table.
This might help you if in your case the change made was recent one. But if any more changes have been made on the table, it will start reflecting the date of the most recent change.
select name, modify_date from sys.objects where name=#table_name
SQL Server does not keep track of specific changes to tables. If you want or need this level of detail, you need to create a DDL Trigger (introduced in SQL Server 2005) that can trap certain specific events or even classes of events, and log those changes to a history table that you create.
DDL Triggers are "after" triggers; there is no "instead of" option. However, if you want to disallow an action, you can just issue a ROLLBACK and that will cancel what happened.
The MSDN page for DDL Triggers has a lot of good information regarding how to trap either specific events (i.e. ALTER TABLE) and using the EVENTDATA function, which returns XML, to get the specifics of what event fired the trigger, including the exact SQL query that was executed. In fact, the MSDN page for Use the EVENTDATA Function even has simple examples of creating a DDL trigger to capture ALTER TABLE statements (in the "
ALTER TABLE and ALTER DATABASE Events" section) and creating a DDL trigger to capture the events to a log table (in the "Example" section). Since all ALTER TABLE commands will fire this trigger, you need to parse out which ones are specific to what you are looking for. And, maybe now that you know that this is an option, capturing more than just adding columns is desired (i.e. dropping columns, changing the datatype and/or NULLability, etc).

Is Views are for SQL Select statement or for any other statement?

are we using SQL Server Views for only Getting(SELECT) the Results or is there any other operations can be performed by using VIEWS.
My Question is i am Trying to Insert some New Records into my table by using Views, is it possible to do this operation by using this Views.
You can, in fact, insert, update or delete using a View. From MSDN:
You can modify the data of an underlying base table through a view, in
the same manner as you modify data in a table by using UPDATE,
INSERT and DELETE statements or by using the bcp utility and BULK INSERT statement.
However, there are restrictions on how you can actually do this. You can read the details on MSDN. In short, the view must only reference columns from one base table, must not contain any computed or derived columns and must not contain grouping clauses.
No, a view is a "virtual table", so you can't execute operations like insert and update.
You have to apply the changes into the original table then the view will reflect the changes.
View
If you are using MS SQL Server, you can use "Stored Procedure". Or similar in other DBMS.

Resources