Use column set for ALL_SPARSE_COLUMNS in the Sql View - sql-server

I have a table where I add sparse columns dynamically:
CREATE TABLE [dbo].[my_table](
[id] [BIGINT] NOT NULL,
[column_set] XML COLUMN_SET FOR ALL_SPARSE_COLUMNS)
I add sparse columns at runtime with the following SQL:
ALTER TABLE my_table ADD my_sparse_column ... SPARSE
I want to create the SQL view for this table:
CREATE VIEW [dbo].[v_my_view]
AS
SELECT v.*
FROM my_table v
However I cannot query data from my sparse columns when I use the view:
SELECT my_sparse_column FROM v_my_view
However, I receive such an error:
This query works fine when executing it on the original table.
Is it possible to make it work?

This behaviour is documented for SPARSE columns when there is a COLUMN_SET present.
Warning:
Adding a column set changes the behavior of SELECT * queries. The query will return the column set as an XML column and not return the individual sparse columns. Schema designers and software developers must be careful not to break existing applications. Individual sparse columns can still be queried by name in a SELECT statement.
So the view will never contain that column, unless you specifically select it, not just using select *.
There is another issue that you would get even if it wasn't SPARSE.
You are adding the column after creating the view.
You need to then run the following statement:
EXEC sp_refreshview N'dbo.v_my_view';
When creating a view, the view is parsed into a compiled expression tree (without any optimizations). Then, when you use the view, the compiler does not simply dump the view text into the outer query. Instead, it parses the outer query into an expression tree, and uses the expression tree from the view in the correct place.
So when you add a column, the expression tree is not updated. So you need to refresh the view definition.
You also need to rebuild any stored procedures which access this table or the view, for the same reason.
EXEC sp_refreshsqlmodule N'dbo.YourProc';
db<>fiddle

Related

How to dynamically exclude non-copyable fields in trigger tables

Background: I am trying to have an after update trigger which stores the changed values dynamically into another table. Since this trigger should be generic and easy to transfer to other tables and won't cause problems, if I add additional columns (If my whole code should be required to solve this, I'll update the question)
While trying to do this, I encounter following issue: I want to store the inserted table into an temporary table, which I do in this way:
SELECT *
INTO #tempINSERTED
FROM INSERTED
But the original table contains both: ntext and timestamp columns which aren't allowed in temporary tables.
Another approach I tried, was looping through the system table INFORMATION_SCHEMA.COLUMNS and build a SQL statement as a string excluding non-copyable columns, but this way I cannot access the inserted table. - I already figured I cannot access inserted if I use sp_executesql.
So my question: is there a way to access the inserted table and exclude non-copyable columns as ntext, text, image ?
Thanks in advance
You want the triggers to run fast. So the better approach would be to generate the create trigger code rather than looping through the fields in the trigger itself. Then if the table schema changes you will need to regenerate the trigger.
For your #TEMPINSERTED table you can use nvarchar(max) in place of ntext,
varchar(max) for text and varbinary(max) in place of image. You can also use and binary(8) or bigint in place of timestamp.
I would suggest using a table variable instead of an #temptable. I.e.:
declare #tempTable table (
fieldname int, -- and so on
)

effect of table hint on view and table used inside that view

We can use table hints like NOLOCK, PAGLOCK
but my question is... If table hints not used in view definition
but used in query with view like
SELECT * FROM myview WITH(nolock)
will this effect on table used inside that view
Logically it should ... cause the view query is going to run against the table as view doesn't store any data by itself (Unless it's a Indexed/Materialized view).
Per Docmentation TABLE HINTS gets propagated to actual table. Little excerpt from the document [Remarks Section]
All lock hints are propagated to all the tables and views that are
accessed by the query plan, including tables and views referenced in a
view. Also, SQL Server performs the corresponding lock consistency
checks.
But it also says that TABLE HINTS won't apply for computed columns computed from some other table column expression.
If a table contains computed columns that are computed by expressions
or functions accessing columns in other tables, the table hints are
not used on those tables and are not propagated. For example, a NOLOCK
table hint is specified on a table in the query. This table has
computed columns that are computed by a combination of expressions and
functions that access columns in another table. The tables referenced
by the expressions and functions do not use the NOLOCK table hint when
accessed.
TEST:
create a table named employee as below
create table employee(id int not null, name varchar(20));
Inserted around 1572866 rows. So it takes sme time to execute.
create a view as below (see view definition has no table hints in place)
create view testview
as
select * from employee;
Select from view with table hint
select * from testview with(paglock,holdlock)
while this is on run .. try doing an insert on employee table and see yourself how insert will keep waiting for the select .. rom view to complete.

How To change the column order of An Existing Table in SQL Server 2008

I have situation where I need to change the order of the columns/adding new columns for existing Table in SQL Server 2008.
Existing column
MemberName
MemberAddress
Member_ID(pk)
and I want this order
Member_ID(pk)
MemberName
MemberAddress
I got the answer for the same ,
Go on SQL Server → Tools → Options → Designers → Table and Database Designers and unselect Prevent saving changes that require table re-creation
2- Open table design view and that scroll your column up and down and save your changes.
It is not possible with ALTER statement. If you wish to have the columns in a specific order, you will have to create a newtable, use INSERT INTO newtable (col-x,col-a,col-b) SELECT col-x,col-a,col-b FROM oldtable to transfer the data from the oldtable to the newtable, delete the oldtable and rename the newtable to the oldtable name.
This is not necessarily recommended because it does not matter which order the columns are in the database table. When you use a SELECT statement, you can name the columns and have them returned to you in the order that you desire.
If your table doesn't have any records you can just drop then create your table.
If it has records you can do it using your SQL Server Management Studio.
Just click your table > right click > click Design then you can now arrange the order of the columns by dragging the fields on the order that you want then click save.
Best Regards
I tried this and dont see any way of doing it.
here is my approach for it.
Right click on table and Script table for Create and have this on
one of the SQL Query window,
EXEC sp_rename 'Employee', 'Employee1' -- Original table name is Employee
Execute the Employee create script, make sure you arrange the columns in the way you need.
INSERT INTO TABLE2 SELECT * FROM TABLE1.
-- Insert into Employee select Name, Company from Employee1
DROP table Employee1.
Relying on column order is generally a bad idea in SQL. SQL is based on Relational theory where order is never guaranteed - by design. You should treat all your columns and rows as having no order and then change your queries to provide the correct results:
For Columns:
Try not to use SELECT *, but instead specify the order of columns in the select list as in: SELECT Member_ID, MemberName, MemberAddress from TableName. This will guarantee order and will ease maintenance if columns get added.
For Rows:
Row order in your result set is only guaranteed if you specify the ORDER BY clause.
If no ORDER BY clause is specified the result set may differ as the Query Plan might differ or the database pages might have changed.
Hope this helps...
This can be an issue when using Source Control and automated deployments to a shared development environment. Where I work we have a very large sample DB on our development tier to work with (a subset of our production data).
Recently I did some work to remove one column from a table and then add some extra ones on the end. I then had to undo my column removal so I re-added it on the end which means the table and all references are correct in the environment but the Source Control automated deployment will no longer work because it complains about the table definition changing.
The real problem here is that the table + indexes are ~120GB and the environment only has ~60GB free so I'll need to either:
a) Rename the existing columns which are in the wrong order, add new columns in the right order, update the data then drop the old columns
OR
b) Rename the table, create a new table with the correct order, insert to the new table from the old and delete from the old as I go along
The SSMS/TFS Schema compare option of using a temp table won't work because there isn't enough room on disc to do it.
I'm not trying to say this is the best way to go about things or that column order really matters, just that I have a scenario where it is an issue and I'm sharing the options I've thought of to fix the issue
SQL query to change the id column into first:
ALTER TABLE `student` CHANGE `id` `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT FIRST;
or by using:
ALTER TABLE `student` CHANGE `id` `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT AFTER 'column_name'

Can you change the column length in a view in SQL Server 2000?

Not sure if this is even allowed, but if so, can someone tell me what the T-SQL is? I've tried the following but to no avail.
alter [View_Name]
alter column [Coln_Name] [New size/length] not null
GO
Any help is appreciated. Thanks!
Not directly.
This is derived automatically from the column expression. You can CAST the expression in the View SELECT list to a particular datatype though.
You would need to change the column length in the underlying table, or to change the SELECT statement forming the view to CAST or CONVERT the column to a different length data type.
Views are ways to see data in other tables; typically the data is simply whatever is in the underlying table, so you would need to change the column there.
However, you can have views that do things like cast() or convert(); these are typically a bad idea, becuase the data needs to be re-fetched every time the view is used, and these operations add overhead. In the design of the view, you can decide to cast as another data type, or do any transformation you would like - but it has overhead, and will not alter the original data.
If you know what the current view selects, you can use something like:
Alter view Viewname[cloumn] as Select cast(original_data as varchar(n)) from Original_Table
I just ran into the same situation. What I did was:
Change the column size in the table that the view looks at.
Create a script to recreate the view (if you don't already have one).
Delete the view
Use the script to recreate the view.
After that the column sizes in the view were the same as the changes I made to the underlying table.
You can not alter the column size in a view as a view is derived from other table. So if you need to change the column size, change the column size of the table. To change the column size use ALTER TABLE as :
ALTER TABLE [Table_Name]
ALTER COLUMN [Column_Name] Data_Type(Size)
After changing the column size you might need to drop the view and recreate it again.
If the length shown in the view doesn't match the underlying table then drop and recreate the view.
Use something like this to investigate the column lengths in the table and view
SELECT o.[name], *
FROM sys.all_columns c
INNER JOIN sys.objects o on o.[object_id]=c.[object_id]
WHERE c.[name] = 'OML'
-- AND c.[max_length]=11
ORDER BY O.[name];
To get the Drop and Create sql I use SSMS and right click context menu (on the view in the Object Explorer), then go to 'Script View as', and 'DROP And CREATE To'.

Is it possible to create an indexed view from Xml Data in Sql Server 2008?

I see from the 2005 documentation that you cannot create an indexed view from an Xml column.
Is this possible in 2008 or 2008R2? I can't find any documentation saying that it is something that was added but am looking for confirmation and I don't have handy access to a 2008 environment at the moment.
EDIT
My motivation behind this is that the amount of Xml is growing to the point where SSRS reports which aggregate data from the Xml are becoming slow.
Depending on your need, what you could do is this:
create a set of stored functions that extract certain bits of key information from your XML (function receives XML as input, extracts the info using XPath/XQuery, returns a VARCHAR or INT or something value)
CREATE FUNCTION dbo.SomeFunction(#Input XML)
RETURNS VARCHAR(20)
WITH SCHEMABINDING
AS BEGIN
......
END
add those key bits to your base table as computed columns that reference those functions, with the PERSISTED keyword:
ALTER TABLE dbo.YourTable
ADD ComputedColumns1 AS dbo.SomeFunction(XmlColumn) PERSISTED
create your view on the table and those computed columns, with schemabinding:
CREATE VIEW vYourView
WITH SCHEMABINDING
AS
SELECT (list of columns)
FROM dbo.YourTable
create a unique, clustered index on that view - unless you've violated any of the requirements of the indexed view, this should work just fine:
CREATE UNIQUE CLUSTERED INDEX CIX_YourView ON dbo.vYourView(.....)
This works fine if you need to extract a small number of key bits of information from an XML column - it's definitely not recommended for lots of XML elements / values.
I don't believe this is possible. Without a better explanation of what you are trying to do, one suggestion I can offer is to pull the XML apart before insert (perhaps using an instead of trigger, or doing this shredding at the application layer) and storing the part(s) you want to use for the indexed view in separate non-XML columns.

Resources