I am now working on a View in SQL Server 2012 which is very long (has around 800 columns). We allow users to add custom columns to the table(A separate UI that allows user to specify column name, type and max length).Once the column is added to the table, it must be reflected in the view too. Is there a way to automatically accomplish this ? Right now, I need to create an alter view statement with the already existing 800+ columns and newly added column. Also, can sp_refreshview be used for this purpose? Looking for some answers. Thanks in advance.
If you manually set which columns are included to view (I mean SELECT column1, column2 FROM), then the automatic update probably isn't possible.
If SELECT * is used in view (bad practice), there is a solution:
exec sp_refreshview [dbo.v_customer]
And its more common form here (update all views).
Related
I've encountered an issue with SQL Server when using an updatable CTE when combining a view with a derived column and a table using system versioning.
It causes a stack dump and disconnects the session with the error:
Msg 596 Level 21 State 1 Line 0
Cannot continue the execution because the session is in the kill state.
Msg 0 Level 20 State 0 Line 0
A severe error occurred on the current command. The results, if any, should be discarded.
I've spent some time getting to the bottom of the cause and am able to reproduce the error on any version of SQL Server.
My query is quite complex however I've boiled it down to the following few requirements:
Create two tables, one will be the target of an update, the other a source of data.
Create a view on the table containing source data.
The view must include a derived column eg select 0 as columnName
The table to update must have system versioning on
Define a CTE to select columns from the view and join to the target table
Update the CTE to set column in target table to the value of the derived column in view
BOOM
If the derived column in the view is replaced with a physical column, or system versioning is disabled, the update works.
It's reproducable and I can demonstrate it with this simple DB<>Fiddle
I'm looking to try and find a workaround. My actual situation is using the updatable CTE to select top N rows from the view of a staging table in order to batch-update a target table (avoiding lock escalation) with the staging table containing 500k - 1m+ rows.
Has anyone encountered this or can maybe think of a clever workaround / hack?
Thanks to some help from the comments, #lptr's suggestion to apply some sort of function to the offending columns turned out to be a valid workaround.
In the CTE that was selecting columns from the view which contained some derived column values I implemented a 1 * columnname as columnname and this made SQL Server happy.
The issue was just having these column in the view, regardless of whether they were used in an update or not.
I have two tables, one called Season the other one Episode. Between them is a Link table that stores SeasonID and EpisodeID. How do I make sure that when a new episode is added the Link table will be updated as well?
Assuming that you are using SQL Service.
We can achieve with the help of trigger like this
Query
CREATE TRIGGER trig_Update_Episode
ON [Episode]
FOR INSERT
AS
Begin
IF NOT EXISTS (SELECT 1
FROM [dbo].[tblEpisodeSession] WITH (NOLOCK)
WHERE [EpisodeId] = [inserted.ID])
PRINT N'You must update an entry in tblSessionEpisode As well';
End
for both the table you should create a trigger like given above.
In example query you can replace message with your actual query which should actually create an entry in tblEpisodeSession.
Hope this helps.
I have a table in SQL Server database. It has a column testrownum. I want to update the testrownum column to be rownum whenever row is created in the table automatically.
Is there any setting that I can turn on to achieve this?
Perhaps it is best to get a row number at the time you SELECT your data, by using the ROW_NUMBER() function.
As others have pointed out (comments section) the data in a table is essentially unordered. You can however assign a row number for a certain ordering when you select data as follows (suppose a table that only has one column being name):
SELECT
name,
rownr=ROW_NUMBER() OVER(ORDER BY name)
FROM
name_table
You can create trigger function.
Trigger is a function which is called every time data is insert, update or delete from table (you can specify when you want your function to be called when creating trigger). So you can add two triggers, one for insert and one for delete and just increment/decrement value you want.
I have two table "Container" and "Control". These are existing tables and there is no foreign key relationship between the two. These are also very old tables so are not normalized. And I cannot change the structure now.
Below is the structure of the two tables.
Container table :
Control Table :
The Name field in Control table contains CTableName+CPName from Container table.
I want to update the columnName field of Control table with the value of CID column of Container table. and also want to insert one more record (for ctable2 i.e the fourth row in final Control table below) in Control table.
The tablename and columnname columns have will always be have default values.
The final Control table should look like this:
How do I do this?
I hope you want to apply this fix because you want normalize your table structure.
Try this:
First step:
In this way you'll UPDATE all Control rows with the value of Container table where the couple fields CTableName and CPName are the same of Name (excluding the rows of Container with the same couple fields)
UPDATE Control
SET ColumnValue = (
SELECT c.CID
FROM Container c
WHERE c.CTableName + '+' + c.CPName = Control.Name
AND NOT EXISTS(
SELECT 'PREVIOUS'
FROM Container c2
WHERE c.CTableName = c2.CTableName
AND c.CPName = c2.CPName
AND c.CID < c2.CID
)
),
TableName = 'default', ColumnName = 'default'
WHERE ColumnValue IS NULL
Second step:
Adding elements don't present in Control table
INSERT INTO Control (field list)
SELECT field list
FROM Container co
WHERE NOT EXISTS(
SELECT 'in_control'
FROM Control ct
WHERE co.CID = ct.ColumnValue
)
After these two steps you can drop column Name in Control table
I am an Oracle plsql programmer and worked with Sql-server as well.
First you should describe the relationship between the 2 tables, in the end i could figger it out but it's better you explain it yourself.
To update a table with information from another table you should ask yourself:
- when should the update take place?
- what are the conditions to start the update?
- how should the update be done?
In Oracle there is a database object called a trigger. It's quite a handy object and probably just what you need. I believe that sql-server has it too.
Pls fee free to ask any questions but do read the sql-server appropriate manual as well.
Good luck, Edward.
So I'm trying to copy some data from database table to another. The problem is though, the target database table has 2 new columns that are required. I wanted to use the export/import wizard on SQL Server Management Studio but if I use that I will need to write a query for each table and I can only execute 1 query at a time. Was wondering if there are a more efficient way of doing it.
Here's an example of 1 table:
dbase1.dbo.Appointment { id, name, description, createdate }
dbase2.dbo.Appointment { id, name, description, createdate, auditby, auditat}
I have a total of 8 tables with those 2 additional columns. and most of them are related to each other via fk, so I wanted to use the wizard as it figures out which table gets inserted first. The problem with that is, it only works if I do a "copy data from one or more tables " and not the "write a query to specify data" (I use this to populate those two new columns).
I've been doing this very slow process in copying data as I'm using MVC Code First for my application and I dont have access to the server to be able to drop and create the table at my leisure. So I have to resort to this to maintain the data that I already have.
An idea: temporarily disable the foreign key constraints in the destination database. Then it doesn't matter what order you run your inserts. In order to populate the two new and required columns, you just need to pick some stock values to put in there (since obviously these rows initially are not subject to initial auditing). For example:
INSERT dbase2.dbo.appointment
(id, name, description, createdate, auditby, auditat)
SELECT id, name, description, createdate,
auditby = 'me', auditat = GETDATE()
FROM dbo.appointment;
Since it seems the challenge is merely that the destination requires columns that aren't in the source, and that you need to determine what should be populated in these audit columns, this seems to solve multiple problems at once. You just need to figure out what to put in there instead of 'me' and GETDATE().
(To get the wizard to pull these 8 tables for you, you might be able to create a view similar to the select portion of the above query, but that's more work and it won't see the underlying FK constraints to generate them in the right order anyway.)
Write the sql query for each of the insert processes in the order you want it. That would be the simplest approach.
Set the Default values for these two columns
Like for AuditAt - Default Date i.e. GetDate()
For AuditBy - The Person ID/Name
Now, you can Insert into these tables without entering for these two columns