SQL Server materialized with ID column auto Increment - sql-server

I want to create a SQL Server table materialized view where I want to add an extra column named ID which is auto increment.
Is that possible?

No, that's not possible. The restrictions on indexed views prevent this.
The ID would not be stable anyway. It would change in unexpected ways when the underlying data changes. The view is not a persistent table. It reflects what the view definition says at all times.
Use something else as the key of the indexed view. Usually, there is a suitable combination of columns from the underlying tables.

Related

Why can't columnar databases like Snowflake and Redshift change the column order?

I have been working with Redshift and now testing Snowflake. Both are columnar databases. Everything I have read about this type of databases says that they store the information by column rather than by row, which helps with the massive parallel processing (MPP).
But I have also seen that they are not able to change the order of a column or add a column in between existing columns (don't know about other columnar databases). The only way to add a new column is to append it at the end. If you want to change the order, you need to recreate the table with the new order, drop the old one, and change the name of the new one (this is called a deep copy). But this sometimes can't be possible because of dependencies or even memory utilization.
I'm more surprised about the fact that this could be done in row databases and not in columnar ones. Of course, there must be a reason why it's not a feature yet, but I clearly don't have enough information about it. I thought it was going to be just a matter of changing the ordinal of the tables in the information_schema but clearly is not that simple.
Does anyone know the reason of this?
Generally, column ordering within the table is not considered to be a first class attribute. Columns can be retrieved in whatever order you require by listing the names in that order.
Emphasis on column order within a table suggests frequent use of SELECT *. I'd strongly recommend not using SELECT * in columnar databases without an explicit LIMIT clause to minimize the impact.
If column order must be changed you do that in Redshift by creating a new empty version of the table with the columns in the desired order and then using ALTER TABLE APPEND to move the data into the new table very quickly.
https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_TABLE_APPEND.html
The order in which the columns are stored internally cannot be changed without dropping and recreating them.
Your SQL can retrieve the columns in any order you want.
General requirement to have columns listed in some particular order is for the viewing purpose.
You could define a view to be in the desired column order and use the view in the required operation.
CREATE OR REPLACE TABLE CO_TEST(B NUMBER,A NUMBER);
INSERT INTO CO_TEST VALUES (1,2),(3,4),(5,6);
SELECT * FROM CO_TEST;
SELECT A,B FROM CO_TEST;
CREATE OR REPLACE VIEW CO_VIEW AS SELECT A,B FROM CO_TEST;
SELECT * FROM CO_VIEW;
Creating a view to list the columns in the required order will not disturb the actual table underneath the view and the resources associated with recreation of the table is not wasted.
In some databases (Oracle especially) ordering columns on table will make difference in performance by storing NULLable columns at the end of the list. Has to do with how storage is beiing utilized within the data block.

Why does indexed view materialize?

If we create an index to a view, we materialize the view.
Why is the view materialized when it is indexed ? What is the signification as opposed to a non-materialized view ?
To my understanding, a normal view don't exist physically. Only its definition is stored, and each reference to the view actually executes the view definition all over again. So when we insert through a view, we insert directly into the table. Is it correct ?
If the view is materialized, it will become a physical table with its data. Then in this case, would modification to the base table is not updated in this view (that has materialized and now lives its own life) anymore ?
Let's think about a table with a clustered index for a minute. When you choose your clustering key, SQL Server creates a b tree, the leaves of which are the actual data. Non-clustered indexes work the same way, except the leaf nodes are tuples that represent your clustering key (so you can traverse the clustered index and get back to the actual data).
Extending the example, when you index a view, you first need to provide a clustered index. What would you expect to live at the leaves of that index? The data of course! :) And any non-clustered indexes on the view will behave exactly like their analogs on a physical table.
As to your question about a materialized view becoming stale, it doesn't. That is, SQL Server knows that the view relies on the table (which is why the view needs to be schema bound so you can't drop one of its constituent tables), and so any DML operations against the constituent tables are also reflected in the table. You can convince yourself of this by creating an indexed view and then looking at a query plan of a simple update to one of the underlying tables. You should see a corresponding update for the indexed view.
A view is simply a select statement that is saved and can be selected from, for convenience. Inserting/updating through a view does go directly to the table to perform its operation.
An indexed view is stored, indexed, just as a table.

SQL Server update query that only update table itself not indexes

I need to write a query that update only table not indexes
because I want to update an int field and don't need to 10 huge index to be updated
If the int field is included in any of the index definitions then they will have to be updated too.
SQL Server won't allow the base table to have one value and the indexes another for obvious data integrity reasons.
If the int field is not included in any of the index definitions then only the table will be updated anyway.
You can disable the indexes but to re-enable them involves rebuilding the whole index.
It depends on what you really want to do
Keeping the index consistent with the table data is the Consistency in ACID. This is how SQL Server and ACID-compliant RDBMSes work.
There are cases such as bulk loads where you want to delay this Consistency. So if you have this use case, DROP or DISABLE the indexes.
If you disable the indexes:
they will never be used for any query-
all associated unique and foreign keys etc will be disabled too
they are not maintained
If you DROP them, of course they can't be used either.
After your bulk load is finished, you enable or create the indexes/constraints again.
If this is what you really want then read MSDN:
Disabling Indexes
Guidelines for Disabling Indexes and Constraints
Perhaps Filtered Indexes are what you're looking for.
This is a SQL Server 2008 feature that lets you create an index that only applies to certain values in a column.

How to create materialized views in SQL Server?

I am going to design a Data Warehouse and I heard about materialized views. Actually I want to create a view and it should update automatically when base tables are changed. Can anyone explain with a query example?
They're called indexed views in SQL Server - read these white papers for more background:
Creating an Indexed View
Improving Performance with SQL Server 2008 Indexed Views
Basically, all you need to do is:
create a regular view
create a clustered index on that view
and you're done!
The tricky part is: the view has to satisfy quite a number of constraints and limitations - those are outlined in the white paper. If you do this, that's all there is. The view is being updated automatically, no maintenance needed.
Additional resources:
Creating and Optimizing Views in SQL Server
SQL Server Indexed Views
Although purely from engineering perspective, indexed views sound like something everybody could use to improve performance but the real life scenario is very different. I have been unsuccessful is using indexed views where I most need them because of too many restrictions on what can be indexed and what cannot.
If you have outer joins in the views, they cannot be used. Also, common table expressions are not allowed... In fact if you have any ordering in subselects or derived tables (such as with partition by clause), you are out of luck too.
That leaves only very simple scenarios to be utilizing indexed views, something in my opinion can be optimized by creating proper indexes on underlying tables anyway.
I will be thrilled to hear some real life scenarios where people have actually used indexed views to their benefit and could not have done without them
You might need a bit more background on what a Materialized View actually is. In Oracle these are an object that consists of a number of elements when you try to build it elsewhere.
An MVIEW is essentially a snapshot of data from another source. Unlike a view the data is not found when you query the view it is stored locally in a form of table. The MVIEW is refreshed using a background procedure that kicks off at regular intervals or when the source data changes. Oracle allows for full or partial refreshes.
In SQL Server, I would use the following to create a basic MVIEW to (complete) refresh regularly.
First, a view. This should be easy for most since views are quite common in any database
Next, a table. This should be identical to the view in columns and data. This will store a snapshot of the view data.
Then, a procedure that truncates the table, and reloads it based on the current data in the view.
Finally, a job that triggers the procedure to start its work.
Everything else is experimentation.
When indexed view is not an option, and quick updates are not necessary, you can create a hack cache table:
select * into cachetablename from myviewname
alter table cachetablename add primary key (columns)
-- OR alter table cachetablename add rid bigint identity primary key
create index...
then sp_rename view/table or change any queries or other views that reference it to point to the cache table.
schedule daily/nightly/weekly/whatnot refresh like
begin transaction
truncate table cachetablename
insert into cachetablename select * from viewname
commit transaction
NB: this will eat space, also in your tx logs. Best used for small datasets that are slow to compute. Maybe refactor to eliminate "easy but large" columns first into an outer view.
For MS T-SQL Server, I suggest looking into creating an index with the "include" statement. Uniqueness is not required, neither is the physical sorting of data associated with a clustered index. The "Index ... Include ()" creates a separate physical data storage automatically maintained by the system. It is conceptually very similar to an Oracle Materialized View.
https://learn.microsoft.com/en-us/sql/relational-databases/indexes/create-indexes-with-included-columns

How to add a constant column when replicating a database?

I am using SQL Server 2000 and I have two databases that both replicate (transactional push subscription) to a single database. I need to know which database the records came from.
So I want to add a fixed column specified in the publication to my table so I can tell which database the row originated from.
How do I go about doing this?
I would like to avoid altering the main databases mostly due to the fact there are many tables I would need to do this to. I was hoping for some built in feature of replication that would do this for me some where. Other than that I would go with the view idea.
You could use a calculated column Use the following on the two databases:
ALTER TABLE TableName ADD
MyColumn AS 'Server1'
Then just define the single "master" database to use a VARCHAR column (or whatever you want) that you fill using the calculated columns value.
You can create a view, which adds the "constant" column, and use it as a replication source.
So the solution for me was to set up the replication publications to allow transformations and create a DTS package for each site that appends the siteid into the tables to keep the ids unique as I can't use guids.

Resources