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
Related
I have an existing database in MS SQL server and want to rename some tables and columns because the names currently used aren't accurate to what it represents.
I have multiple web and desktop applications that access the database, using Entity Framework (code first). Too many to update in one go and cannot afford for all apps to start working.
I was thinking it was nice is SQL server allowed a 'permanent' alias for tables and columns but I don't think this feature exists.
Or I was wondering if there was a way in EF to have two names for the same property?
For the tables, you could rename them and then create a synonym with the old name pointing to the new name.
For the columns, changing their name will break your application.You could create computed columns with the old name as well, that simply display the value of the new named column though (but this seems a little silly).
Note, however, that a computed column cannot reference another computed column, so you would have to duplicate the column in its entirety. That could lead to problems down the line if you don't update the definition of both columns.
A view containing a simple select statement acts exactly like a table. You really need to fix this properly across the database and applications. However if you want to go the view route, I suggest you do this:
Say you have a table called MyTable that you rename TheTable and with a column called MyColumn that you want to rename to TheColumn
Create a schema, say, new
Move the original table into it with this ALTER SCHEMA new TRANSFER MyTable
Rename the table and column.
Now you have a table called new.TheTable with a column called TheColumn. Everything is broken
Lastly, create a view that looks just like the old table
CREATE VIEW dbo.MyTable
AS
SELECT Column1, Column2, Column3, TheColumn As MyColumn
FROM new.TheTable;
Now everything works again.
All your fixed 'new' tables are in the new schema
However now everything is extra complicated
This is basically an illustration that you should just fix it properly across the whole app one at a time with careful change management. Definitely don't complicate it with triggers
Since you are using code first with multiple web and desktop applications, you are likely managing database changes from one place through migrations and ignoring changes other places.
You can create an empty migration and add code that will change the table name and column names to what you want. The migration should then create a view that will select from that table with the original table and column names. When you apply this migration, everything should still be working as normal from all applications. There are no model changes since you didn’t touch the model classes. Inserts, updates, and deletes will still happen through the view. There is no need for potentially buggy triggers or synonyms on the table in this option.
Now that you have the table changed, you can focus on the application code. If it helps, you can add annotations over the column and table names and start refactoring the code. You need to make sure you don’t make model changes that will break the other apps. If apps ignore model changes, you can get away with adding annotations over the columns and classes on all the apps before refactoring. You can get rid of the view sooner this way.
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 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.
What is a view in Oracle?
A View in Oracle and in other database systems is simply the representation of a SQL statement that is stored in memory so that it can easily be re-used. For example, if we frequently issue the following query
SELECT customerid, customername FROM customers WHERE countryid='US';
To create a view use the CREATE VIEW command as seen in this example
CREATE VIEW view_uscustomers
AS
SELECT customerid, customername FROM customers WHERE countryid='US';
This command creates a new view called view_uscustomers. Note that this command does not result in anything being actually stored in the database at all except for a data dictionary entry that defines this view. This means that every time you query this view, Oracle has to go out and execute the view and query the database data. We can query the view like this:
SELECT * FROM view_uscustomers WHERE customerid BETWEEN 100 AND 200;
And Oracle will transform the query into this:
SELECT *
FROM (select customerid, customername from customers WHERE countryid='US')
WHERE customerid BETWEEN 100 AND 200
Benefits of using Views
Commonality of code being used. Since a view is based on one common set of SQL, this means that when it is called it’s less likely to require parsing.
Security. Views have long been used to hide the tables that actually contain the data you are querying. Also, views can be used to restrict the columns that a given user has access to.
Predicate pushing
You can find advanced topics in this article about "How to Create and Manage Views in Oracle."
If you like the idea of Views, but are worried about performance you can get Oracle to create a cached table representing the view which oracle keeps up to date.
See materialized views
regular view----->short name for a query,no additional space is used here
Materialised view---->similar to creating table whose data will refresh periodically based on data query used for creating the view
A view is a virtual table, which provides access to a subset of column from one or more table. A view can derive its data from one or more table. An output of query can be stored as a view. View act like small a table but it does not physically take any space. View is good way to present data in particular users from accessing the table directly. A view in oracle is nothing but a stored sql scripts. Views itself contain no data.
A view is simply any SELECT query that has been given a name and saved in the database. For this reason, a view is sometimes called a named query or a stored query. To create a view, you use the SQL syntax:
CREATE OR REPLACE VIEW <view_name> AS
SELECT <any valid select query>;
If I'm adding a column to a table in Microsoft SQL Server, can I control where the column is displayed logically in queries?
I don't want to mess with the physical layout of columns on disk, but I would like to logically group columns together when possible so that tools like SQL Server Management Studio list the contents of the table in a convenient way.
I know that I can do this through SQL Management Studio by going into their "design" mode for tables and dragging the order of columns around, but I'd like to be able to do it in raw SQL so that I can perform the ordering scripted from the command line.
You can not do this programatically (in a safe way that is) without creating a new table.
What Enterprise Manager does when you commit a reordering is to create a new table, move the data and then delete the old table and rename the new table to the existing name.
If you want your columns in a particular order/grouping without altering their physical order, you can create a view which can be whatever you desire.
I think what everyone here is missing is that although not everyone has to deal with 10's, 20's, or 1000's instances of the same software system installed throughout the country and world, those of us that design commercially sold software do so. As a result, we expand systems over time, expand tables by adding fields as new capability is needed, and as those fields are identified do belong in an existing table, and as such, over a decade of expanding, growing, adding fields, etc to tables, and then having to work with those tables from design, to support, to sometimes digging into raw data/troubleshooting to debug new functionality bugs, it is incredibly aggravating to not have the primary information you want to see within the first handful of fields, when you may have tables with 30, 40, 50, or even 90 fields, and yes, in a strictly normalized database.
I've often wished I could do this, for this exact reason. But short of doing exactly what SQL does, building a Create Script for a new Table the way I want it, writing the Insert to it, then dropping all existing constraints, relationships, keys, index, etc etc from the existing table and renaming the "new" table back to the old name, and then reading all those keys, relationships, index, etc etc ....
It's not only tedious, time-consuming, but ... in five more years, it will need to happen again.
It's so close to worth that massive amount of work, however the point is, it won't be the last time we need this ability, since our systems will continue to grow, expand, and get fields in a wacked ordered driven by need/design additions.
A majority of developers think from a single system standpoint that serves a single company or very specific hard box market.
The "off-the-shelf" but significantly progressive designers and leaders of development in their market space will always have to deal with this problem, over and over, and would love a creative solution if anyone has one. This could easily save my company a dozen hours a week, just not having to scroll over, or remember where "that" field is in the source data table.
When Management Studio does it, it's creating a temporary table, copying everything across, dropping your original table and renaming the temporary table. There's no simple equivalent T-SQL statement.
If you don't fancy doing that, you could always create a view of the table with the columns in the order you'd like and use that?
Edit: beaten!
If I understand your question, you want to affect what columns are returned first, second, third, etc in existing queries, right?
If all of your queries are written with SELECT * FROM TABLE - then they will show up in the output as they are laid out in SQL.
If your queries are written with SELECT Field1, Field2 FROM TABLE - then the order they are laid out in SQL does not matter.
There is one way, but its only temporarily for the query itself. For example,
Lets say you have 5 tables.
Table is called T_Testing
FirstName, LastName, PhoneNumber, Email, and Member_ID
you want it to list their ID, then Last Name, then FirstName, then Phone then Email.
You can do it as per the Select.
Select Member_ID, LastName, FirstName, PhoneNumber, Email
From T_Testing
Other than that, if you just want the LastName to Show before first name for some reason, you can do it also as follows:
Select LastName, *
From T_Testing
The only thing you wanna be sure that you do is that the OrderBy or Where Function needs to be denoted as Table.Column if you are going to be using a Where or OrderBy
Example:
Select LastName, *
From T_Testing
Order By T_Testing.LastName Desc
I hope this helps, I figured it out because I needed to do this myself.
Script your existing table to a query window.
Run this script against a Test database (remove the Use statement)
Use SSMS to make the column changes you need
Click Generate Change Script (left most and bottommost icon on the
buttonbar, by default)
Use this script against your real table
All the script really does is create a second table table with the desired column orders, copies all your data into it, drops the original table and then renames the secondary table to take its place. This does save you writing it yourself though should you want a deploy script.
It is not possible to change the order of the columns without recreating the whole table. If you have a few instances of the database only, you can use SSMS for this (Select the table and click "design").
In case you have too many instances for a manual process, you should try this script:
https://github.com/Epaminaidos/reorder-columns
It can be done using SQL, by modifying the system tables directly. For example, look here:
Alter table - Add new column in between
However, I would not recommend playing with system tables, unless it's absolutely necessary.
Open your table in SSMS in design mode:
Reorder your columns:
It is important to not save your change.
Click the "Generate Change Script" button:
Now a window will open that contains the script to apply this change:
Copy the text from the window.
In this instance, it generated the following code:
/* To prevent any potential data loss issues, you should review this script in detail before running it outside the context of the database designer.*/
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Tmp_MyTable
(
Id int NOT NULL,
Name nvarchar(30) NULL,
Country nvarchar(50) NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Tmp_MyTable SET (LOCK_ESCALATION = TABLE)
GO
IF EXISTS(SELECT * FROM dbo.MyTable)
EXEC('INSERT INTO dbo.Tmp_MyTable (Id, Name, Country)
SELECT Id, Name, Country FROM dbo.MyTable WITH (HOLDLOCK TABLOCKX)')
GO
DROP TABLE dbo.MyTable
GO
EXECUTE sp_rename N'dbo.Tmp_MyTable', N'MyTable', 'OBJECT'
GO
COMMIT
As you can see, what it does is 1) create a new temporary table, 2) copy the data over to the temporary table, 3) delete the original table and 4) rename the temporary table to the original table's name.