Why would I update a value in a view? [closed] - sql

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Just a quick question on my MCSA SQL Server 2012 course.
As part of an exercise I've been asked to create a trigger to stop any updates on a view, I first checked that I could indeed change a value of a column on the view.
Having worked with views before I know what they are, but I dont know why a view wouldn't stop a change in the first place by default anyway.
1) Why might I want to change a value in the view table?
2) Also if I updated a value on the view, would anything change it back to reflect what is in the base tables and if so when might that happen?, ie an overnight refresh, any change to the base table?
Thanks :)

Your question seems to be more concerned with "why" rather than "how." Why would DML be executed against a view instead of directly against a table? The answers are almost too numerable to list here, but here are just a couple of the bigger ones.
For starters, when I design a database, almost every table has at least one view defined for it. If more than one, one is normally the DML view and the others are read-only (trigger that does nothing). No outward-facing and very few inward-facing apps have direct access to the tables. Everything must go through the views.
Why? Because this builds a wall of abstraction between the apps and the underlying tables. I can then constantly tune and tweak the tables and rarely have to make any changes to the apps. I can add or drop columns, change the data type of columns, merge tables together or split a table into two or three separate tables, but the views bring everything back together to how the apps expect to see it. They don't even have to know any changes were made. The apps can write data to what they see as a single "table" and the view trigger assigns the data to the correct tables. The view triggers know how the actual data is stored, the apps don't have to know.
Here's one advantage that is unbeatable. There are many, many useful functions that require the use of a before trigger. Sometimes you just really want to manipulate the data in some way before it goes to the table. Some DBMSs, even major players like SQL Server, have only after triggers. Such a pain.
But front the table with a view, write a trigger on the view, et voila, instant before trigger. This is even handy with other DBMSs like Oracle in that the trigger can update other associated rows in the same table without running afoul of a mutating table condition. I am at this very moment writing a trigger on a view that must update values in several rows every time any Insert or Delete is executed and sometimes for an Update. Almost impossible task without views -- it would have to be done with stored procedures rather than "direct" DML. Handy for me, handy for the apps. Life is good!
Also, take the loop condition caused by trying to keep two tables synched with each other. Any changes made in either table should be sent to the other table. But a trigger on both tables that just mirrors the operation to the other table will create an infinite loop as that trigger turns around and sends it right back. But a trigger on a facing view can perform the DML on its underlying table and on the mirrored table. The view on the mirrored table does the same thing. But since both views operate directly on the tables, there is no infinite loop condition to fall into.
So my question would be more like: why would we ever want users to directly access tables rather than have them go through views?

to answer the question on how to accomplish this with a trigger, you can use the following:
CREATE TRIGGER dbo.demo_trigger ON dbo.demo_view
INSTEAD OF UPDATE --The "INSTEAD OF" is probably why the question is in the course, outside of a view or procedure this is tends to be "BEFORE"
AS
BEGIN
SET NOCOUNT ON
ROLLBACK
RAISERROR (50005,10,1,N'abcde')
END
GO
I added a custom error with this:
sp_addmessage #msgnum = 50005
, #severity = 10
, #msgtext = N'Not allowed';
GO
It can be removed again with this:
sp_dropmessage #msgnum = 50005;
Trying to update the view now gives this result:
Not allowed
Msg 3609, Level 16, State 1, Line 1
The transaction ended in the trigger. The batch has been aborted.

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.

Is it a good idea to have multiple jobs in one stored procedure? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
What is the best practice about this situation?
I want to do multiple DIFFERENT operations on a single entity in my database.I want to insert data, delete rows and etc(basic functionalities only) and I was wondering if it is a good idea to do all of them in one stored procedure using a flag parameter like this:
CREATE PROCEDURE usp_entity
#flag INT
#id AS INT = 0
#field AS VARCHAR = NULL
AS
BEGIN
IF #flag = 1
INSERT INTO entity (field) VALUES (#field)
ELSE IF #flag = 2
DELETE FROM entity WHERE id = #id
END
Or is it better to create different stored procedures like ups_entity_insert and usp_entity_delete to accomplish these tasks?
The reason I am asking this is because one of our teachers did the first approach the other day and I am not sure if it is the right way
In SQL Server, this is probably a bad idea. SQL Server compiles all the queries in a stored procedure the first time it is run. Using a flag to distinguish among different code paths can result in inefficient execution plans for the remaining queries.
Of course, having multiple queries in a stored procedure is a good idea if the queries are related. In general, you want to think of a stored procedure as "doing something", often encapsulating multiple steps. So, you might want to:
Log that an action is being taken
Insert rows into one table
Update rows in another table
and so on
These are all "one thing", so they belong together.
Also, in SQL Server, never use varchar without a length parameter. The default varies by context and this can cause errors that are hard to find. And, don't compare a varchar to an integer. Mixing types is confusing for a human reader and can sometimes confuse the optimizer as well.
I want to do multiple DIFFERENT operations on a single entity in my
database.I want to insert data, delete rows and etc(basic
functionalities only) and I was wondering if it is a good idea to do
all of them in one stored procedure using a flag parameter like this:
I would not do this. It is less clear to people who inherit your code down the road about what it actually does. Making different stored procedures named appropriately is way easier to maintain and is more descriptive to other people.
Always code as if the person who ends up maintaining your code is a
violent psychopath who knows where you live. - Martin Golding
Security is another reason to keep them separate. If you place multiple operations in one procedure, it's an all or nothing approach. Many times certain applications need to read data, but I don't want them to update or maybe insert. There are other times when I need to delete data, but I really want to control who has access to that.
In general this is called CRUD. Basic actions performed over any entity: create, read, update, delete. In your example you have two scenarios: for insert and for delete; also it may include regular update work - I think this is absolutely okay to have these operations within one SP since all three of them are:
DML
perform actions based on specific single record
do not return any dataset.
Including here read operation I think would be a mistake - SP then would sometimes return resultset sometimes not - which is obviously a confusing behavior.
Other option is to have three SPs (I don't mention here read operation) for every action: one for insert, one for update, one for delete. This does not sound wrong until you multiply it on amount of entities. Let's say you have 500 entities which means you have 1500 CrUD SPs. Or only 500 CrUD SPs.
If you have separate SPs for insert/update/delete then you probably have to copy and paste parameter validation code, calls to logging and checking permissions SPs and so on. While there is still only one unique statement and all the rest is similar.
Update and Delete are usually performed on single record, Insert values does not have select part so I don't see any troubles with execution plan or something. And note that SQLSERVER can recompile separate statement instead of recompiling full SP since mssql2005 if I'm not mistaken.
To have SP on each operation is okay too, the only trouble you will possibly have - the number of SPs. If you produce them with code-generation tool or any kind of ORM so this work is well automated (remember refactoring, including some "low-level" work like logging/tracing/security/business rules/validation) then of course there is no need to think of number of SPs and may be it will even be more comfortable to have separate SP on every action.And, of course, if your SPs are very smart, have tons of code for every scenario then as you can understand it yourself it would be easier to maintain them separately. Because else it would be simply hard to understand'em.
And again, including code for rather different purposes is a horrible idea that has no excuses.

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.

Add surrogate id key to keyless tables in legacy database; how might it affect business applications that talk to the database? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am asking this because we worked with legacy database all the time and it can be a problem with you try to put an ORM on a table without primary keys. In this forum, many respondents to this problem have said (quite nonchalantly, in my opinion), just add a primary key to the table. No big deal.
Now I am asking, if you suddenly add primary keys to tables in existing database, what possible negative effects can you imagine, especially to client application? if the question is too broad, that pretty much already answer my question.
Before you start, make sure there's not some other mechanism in place to enforce uniqueness. For example, a not null unique declaration is behaviorally equivalent to a primary key declaration. There might be triggers; there might be privileges that require database updates to go through a stored procedure; there might be other mechanisms I haven't thought of this morning.
You seem to be talking about something like adding a column that's an autoincrementing integer, and declaring that to be the primary key.
Assuming that currently there really is no primary key, and assuming there's no other equivalent to a primary key, the main issues involve application code that relies implicitly on either the order of columns or on the number of columns.
For example, this is a valid SQL statement. You might find something like this embedded in application code.
select *
from your_table
order by 1 desc;
That statement will sort the result set in descending order by the values in the first column.
If you add a column to that table, and you position that column as the first column in the table definition, that SQL statement will start returning data in a different order than the other client expects.
Some platforms don't allow an alter table statement to change the order of columns; new columns go only at the end of the table definition. But even on those platforms, the DBA can dump data, rewrite the create table statement with the new column first, and reload the data.
This kind of issue--changing the number of columns in a table--can break some data imports and exports.
Insert statements written without column names, like insert into foo values (...) might fail.
Statements like these might also appear in triggers, but that's more a problem with database code than with application code.
There's some chance of performance issues. Using the new column as a clustered index--an option on some platforms--will change the physical order of rows. That will certainly change performance, but I can't predict whether that will certainly be a bad thing. The table will be wider--but not much wider--which means slightly fewer rows will fit on a page on disk.
A resilient solution
Change the name of the existing table. (This is simple, but might not be easy.)
Create an updatable view having the same structure and name as the original table.
Change the structure of the original table.
All application code that used the name of the original table will now use the name of the updatable view instead. Since the view's structure and behavior are identical to the original table, all of the application code should just continue to work. (I'd be surprised if application code needed to know whether it was dealing with a table or a view, but that's a possible problem.)
Precautions
In any case, you shouldn't make this change in production first. You should make the change locally first, then in your test environment, and finally--when you've exhausted our collective imaginations--move to production.
And move to production a little at a time. Add the column, and wait a while. Populate the column, and wait a while. Repeat until done.

Change SQL Query update time

I'm reasonably new to using SQL, so I apologise if this is a newbish question!
I'm wanting to be able to view the results of a query in a graph on my website. The problem however is the query takes 2-3 seconds to process (due to a Distinct count over 200,000+ fields), and could likely be called multiple times a second.
If I put the query in a view instead, and have my graph access the view, is there anyway I can set the view to update periodically instead of everytime someone goes to the site? Or is there another way round this?
EDIT: DBMS is MySQL
You could populate the data using a sproc or even just a normal TSQL if you want, using a Scheduled Job. Or, as Gijo suggested, you could look at database replication, but I am not sure that you need that kind of overhead if you can get away with the first choice of periodically caching the data.
You may try replication. With replication, you can set to populate a certain table to get data from a stored procedure and then use this table to show the graph.