ALTER TABLE with a default: SQL Server vs Oracle - sql-server

We have some tables in an Oracle database with several million rows. When we alter one of these tables to add a new column, we specify a default. This is very slow to run as Oracle has to update all existing rows with the default. The solution is to ensure the column is defined as NOT NULL because then Oracle (recent versions only) will not update all existing rows with the default - the subsequent presence of a null in one of these columns tells Oracle that it requires a default and it will provide the default on the fly.
My question is regarding SQL Server: does it exhibit similar behaviour when adding a column and providing a default? If not, are there any best practices in efficiently adding new columns with default values, and are there any advantages in defining a column as NOT NULL?

Prior to SQL Server 2012 adding a NULLable column w/o default was very vast, but adding a DEFAULT contraint would be slow, as every row has to be updated. Since SQL Server 2012 adding a DEFAULT is also fast, a metadata only operation, when possible.

Related

Collation change on MS sql server 2012

Dear all, Currently I am just researching how I could handle the change of the collation on the database.
Somebody made an unusual decision to create accent sensitive database for global use... but I am on the way to handle this!
REASON: of changing the collation is that database contains data collected from different countries and as we all know some of cultures have their own letters.
With the respect for the customers, our organization would like to have Accent Insensitive database. That will allow users to request data from the server without any limitations using local characters.
As far as I have find out, there may be an option to drop constraints and etc. change collation and then just to bring everything back. In this case I am afraid if this would be enough to affect already existing data (columns).
Another way, I have found an article in Collation change on 2005 and 2008 server. However, this does not include the 2012 server.
Also I am taking the complexity of this example into consideration as well.
I believe that I am not in an easy phase. But I am hoping to get few advises what would be the best and safest way to handle this.
Thank you for your concerns and assistance.
UPDATE let me add what architecture do we have: The complete system contains 4 databases and more than 1.000 tables in total. So my expectations is that not all of the possible ways may work in an optimal way.
me too i had to deal with a similar issue because of a different reason: ancient databases with an old SQL collation installed ages ago on a SQL6.5 server that has been inplace upgraded for each version from sql 7 to sql 2005 and now should be updated to sql 2012.
why all these inplace upgrades? because the actual collation was the server collation and was so old that is not available during then install process of a recent version (2000+) of sql server...
i decided to drop all that old rubbish so i had to find a way that allowed me to move to a new installation with a windows collation.
i had to exclude the data migration (create a new database and import data) because of the lack of documentation and the huge number of customizations, triggers, hidden rules and so on.
the solution i used (the order matters):
disable automatic statistics generation
script the creation of all foreign keys and then drop them
script unique and primary indexes and then drop them
script all remaining indexes and then drop them
script custom statistics and then drop them
script CHECK and DEFAULT constraints and then drop them
now you can run the ALTER commands needed to change the collation of the columns and change the collation of the database itself.
when done repeat the above in reverse order to rebuild all the needed objects.
it happens that if the database is so old as is mine you may incur in something funny like existing foreign key that references fields with different datatypes.
Changing collation of all existing columns is a real pain. I suggest a side-by-side migration rather than alter each column individually. Create a new database with the desired collation containing only empty tables. Copy data from the old db to the new one using INSERT...SELECT (or the ETL tool of your choice), and then create constraints, indexes, and other database objects.
Consider upvoting the Make it easy to change collation on a database SQL Server feature request.
There are a number of complicated solutions on the internet for inplace collation changes but the simplest (and safest) way we have found is to script out the database, alter the script to create a new db with the collation set at the start and then import the data to the new database.
We achieve this using MS SQL Server 2012 Management Studio in the following way:
Script out all database objects with Tasks -> Generate Scripts -> Script entire Database and all Database objects
Alter the script with the following 2 changes and then run it to create a new database:
a) Change DB name to MY-NEW-DB
b) Under the CREATE DATABASE statement add: ALTER DATABASE [MY-NEW-DB] collate Latin1_General_CS_AS
If desired, use a tool like RG SQL Compare to compare the old and new database to verify all indexes, constraints, types etc were the same and collation on relevant columns only was changed.
Run Tasks->Import Data ensuring 'Enable Identity Insert' checked. All data transferred to the new case sensitive database correctly.
Run DBCC CHECKDB if you wish to check consistency

Does FluentMigrator support creating a filtered index?

Is it possible to create a filtered index with FluentMigrator? The scenario is that I want to create a unique index on a column that may contain NULLs, so the filter should exclude rows with NULL for the indexed column.
I've modified an index in SQL Server 2012 generated by FluentMigrator to use such a filter and can confirm that it works well, so the remaining piece of the puzzle is to generate this option.
As this is a very Sql Server specific feature you might as well fall back to sql.
One of the reasons for the fluent style is that it is not database specific so the same migration can be run for different database types. But if you are only ever going to use Sql Server and want to use database specific features then the great thing about FluentMigrator is that it allows you to execute sql statements. This is recommended for advanced stuff that we will never support in FluentMigrator and for changes in Stored Procedures.
It would simply be:
Execute.Sql(#"CREATE NONCLUSTERED INDEX FIBillOfMaterialsWithEndDate
ON Production.BillOfMaterials (ComponentID, StartDate)
WHERE EndDate IS NOT NULL;");
Postgres has partial indexes too so this could be something that we will add to FluentMigrator in the future.

Message: This row was successfully committed to the database. However, a problem occurred

I have a table in SQL Server 2005 whose primary key is an identity column (increment 1), and I also have a default value set for one of the other columns.
When I open the table in SQL Server Management Studio and type in a new record into the table, the inserted values are not displayed, and I get the following message on save:
However, if the table has either an identity column, or one or more columns with a default value specified, the inserted value(s) will be displayed in the table after a save. And can be edited.
I frequently create test data in ssms this way and this issue makes it cumbersome to do some things I would like to.
Is there any way around this?
Right click on it and say Execute SQL...it should not display it(error)..its just sql server way of doing things..since it inserts the identity column later..You should not add records in that way in the first place.
You should not add records to a database that way! It can have unfortunate side effects (especially on large tables) as you have discovered.
Records for lookup tables should be added through rerunable scripts. Those scripts should in source control. This makes them easy to promote from dev to Qa to staging to prod.
Test records should also be done in scripts (including scripts to remove the test records) so that you can run thenm on other environments as well as being able to delete and recreate them if some process you are testing went bad. These too should eb in source control (as should all database changes which also should not be done through the GUI).

SSMA timestamp. What's it for, how is it used?

I rencently used the SQL Server Migration Assistant to import a database into SQL Server 2005. I noticed that a number of tables that were imported have been ammended with a new column called SSMA_timestamp.
Can anyone tell me what this is for and how it would be used?
The added SSMA_timestamp columns are not only used during migration. They actually help avoid errors when Access updates records in tables linked to SQL Server. So if you are still using an Access front end linked to the migrated SQL Server database, it would be best to not drop the SSMA_timestamp columns.
From the MSDN article Optimizing Microsoft Office Access Applications Linked to SQL Server:
Supporting Concurrency Checks
Probably the leading cause of updatability problems in Office Access–linked tables is that Office Access is unable to verify whether data on the server matches what was last retrieved by the dynaset being updated. If Office Access cannot perform this verification, it assumes that the server row has been modified or deleted by another user and it aborts the update.
There are several types of data that Office Access is unable to check reliably for matching values. These include large object types, such as text, ntext, image, and the varchar(max), nvarchar(max), and varbinary(max) types introduced in SQL Server 2005. In addition, floating-point numeric types, such as real and float, are subject to rounding issues that can make comparisons imprecise, resulting in cancelled updates when the values haven't really changed. Office Access also has trouble updating tables containing bit columns that do not have a default value and that contain null values.
A quick and easy way to remedy these problems is to add a timestamp column to the table on SQL Server. The data in a timestamp column is completely unrelated to the date or time. Instead, it is a binary value that is guaranteed to be unique across the database and to increase automatically every time a new value is assigned to any column in the table. The ANSI standard term for this type of column is rowversion. This term is supported in SQL Server.
Office Access automatically detects when a table contains this type of column and uses it in the WHERE clause of all UPDATE and DELETE statements affecting that table. This is more efficient than verifying that all the other columns still have the same values they had when the dynaset was last refreshed.
The SQL Server Migration Assistant for Office Access automatically adds a column named SSMA_TimeStamp to any tables containing data types that could affect updatability.
I think this is generated so that the Migration assistant can detect changes to the data during the migration.
Unless you are continuing to use Access as a front end to this specific database you have migrated to SQL Server (in which case see Simon's answer), I don't think they will be used for anything after migration is complete, so it should be safe to drop these new columns once you are sure everything is done.
<!-- Set project preference.
Preference path/name/value can be found in preferences.prefs file stored in SSMA project directory.
Preference path is the node name path starting from root to leaf node separating by "/". -->
<set-project-preference preference-path="prefs/ssma-for-access/a2ss/conversion"
preference-name="timestamp-columns-opt"
preference-value="never" />
From SSMA GUI you can also click tools--> default project setting --> conversion --> Tables --> add timestamp columns --> set to Never

When should you enable the RowGuid column property in SQL Server 2005?

The MSDN documenation states:
Indicates whether SQL Server uses the column as a ROWGUID. You can set this value to Yes only for a unique identity column.
This doesn't tell me why I would have this enabled or disabled.
Setting the column as ROWGUID tells SQL Server that that row will be used as a GUID. By default SQL Server will set the default value of the row to NewID() which will generate a GUID.
So, you would use it when you want to use GUIDs, which are globally unique. This makes them useful for replicating and merging databases since you know that no two rows will ever (theoretically) have the same id.

Resources