Schema change table rebuild - sql-server

I'm working on a script to keep table schemas synchronized.
Is there an exhaustive list of actions done to a table schema in MS SQL that requires the table to be dropped and recreated and the data to be reinserted?

You may be better off standardizing on the CREATE-COPY-DROP-RENAME (CCDR) strategy and only attempting an in-place alter in the few scenarios where your DDL will not require a rebuild rather than trying to compile the exhaustive list. This is the strategy described here: link.
AFAIK, you are only permitted to add columns to an existing table (without rebuilding) if the column is:
added to the end of the table AND
is nullable or has a default constraint
In all other cases, MSSQL will potentially fail if it does not know what to use as a value in the rows of the newly added column or data loss is a result (truncation for example). Even defaulted columns added in the middle will force a rebuild.
To further complicate things, in some cases the success of your deploy will depend on the type of data in the table, and not simply the schema involved. For example, altering a column length to a greater value (varchar(50) --> varchar(100)) will likely succeed; however, decreasing the length is only sometimes permitted. Migrating data type changes is another tricky mess.
In short, I would always rebuild and rarely alter in place.
--
To illustrate in-row data affecting outcome:
create table dbo.Yak(s varchar(100));
insert into dbo.Yak
values(replicate('a', 100));
go
-- attempt to alter datatype to 50 (FAIL: String or binary data would be truncated.)
alter table dbo.Yak
alter column s varchar(50);
go
-- shorten the data in row to avoid data loss
delete from dbo.Yak;
insert into dbo.Yak
values(replicate('a', 50));
go
-- again, attempt to alter datatype to 50 (SUCCESS)
alter table dbo.Yak
alter column s varchar(50);
go
select len(s),* from dbo.Yak;
go
--cleanup
drop table dbo.Yak;
go

In Management Studio, select the table you want to change and right-click Design. Change the datatype of a column in the table design window (tested with int to money).
Instead of saving, right-click in the window and select "Generate Change Script". Copy the SQL statements from the dialog.
*) In previous versions (SQL2000), any changes would recreate the whole table (as far as I remember). It seems that renaming and adding columns have been optimized to ALTER TABLE statements.

I've gotten pretty spoiled by using Visual Studio Database Projects to manage this sort of thing. Once my schema is imported into a project, I can make whatever change I want, and the VSDP will figure out whether the change can be done w/o dropping objects (with an ALTER, for example), or whether it needs to create a new object and copy values over from the old one (which it does automatically).
Plan on a little work to understand how you'll fit this into your specific environment and workflow, but I've found the effort to be very worthwhile.

Related

Snowflake alter column to have default value

I have a table in snowflake. I want to alter one column so that it can have the default value.
Following is the structure:
I want to set the default value for LAST_UPDATED column.
I am running this query:
alter table "TEST_STATUS" modify LAST_UPDATED set default CURRENT_TIMESTAMP() ;
I am getting error as:
Unsupported feature 'Alter Column Set Default'.
How do I alter the table?
You can not use ALTER TABLE to change the default for a column unless it's a sequence or add a column default.
Check Default Values section in here
You need to recreate your table
a default value on a table has to behaviors,
when null use 42, which can be done implemented as read operation
when inserting null use a more complex form to set a value. like seq() or current_date(), this can only be done on write.
The latter form on some data bases just "rewrites" the data then and there, but given Snowflake is a no free lunch/no hidden costs. If you want your table rewritten (to push on a complex new value like the second case) you should rewrite your table. When you have a simple table with 10 rows, this can seem absurd, to make you jump through hoops like this. But when you have tables with terabytes of data, rewriting all that data take a lot of compute time and more importantly is definitely not atomic, thus it needs to be intentionally done as put of a structured data migration process.
Which like nearly everything about Snowflake, it's designed to do heavy lifting, and thus big tasks should be planned tasks. Thus a large rewrite might be a bigger warehouse, and pausing ingress data processes.

Quickly dropping and re-creating multiple indexes, views, statistics when altering a column

I have a column "StoreNumber" in my "Project" table which I want to change to be "NOT NULL". I recently sanitized all of the old data so that there are no null entries. However, when I execute the following statement it fails due to multiple dependencies to various views, indexes, and statistics
ALTER TABLE [Project]
ALTER COLUMN StoreNumber VARCHAR(9) NOT NULL
GO
What is the fastest way to drop all of these views/indexes/statistics then run the alter statement, and then recreate all of the views/indexes/statistics again? I know that I could copy out all of the drop and create statements one by one but I would prefer to generate the script in a single query.
On a side note, why does SQL Server care if I'm making the column more restrictive? The data does not contain nulls and I'm not altering the data type or the size of the columns. How would this type of change ever break a dependent view, index, or statistics? I'm sure there is sound reasoning that I'm not seeing but I would like an example.
Just thinking; will it work if you set a default value first? (dind't check the sintax myself)
ALTER TABLE Project
ADD CONSTRAINT col_sn_def
DEFAULT '' FOR StoreNumber;
GO
The following will drop multiple indexes. Note that the final statement does not include the comma.
DROP INDEX [index1_1] ON [schema].[table1],
[index1_2] ON [schema].[table1],
[index2_1] ON [schema].[table2],
[index3_1] ON [schema].[table3],
...n,
[lastIndexToDrop] ON [schema].[tableName]
Drop View looks like this. Note the semicolon to terminate the statement.
DROP VIEW [schema].[view1], [schema].[view2];
I am only concerned with Indexes in my application at this time. To quickly recreate the indexes, I am reading a .sql file into code and executing it in an ExecuteNonQuery call. If I had views to consider, I would follow the same method of reading from a file into a command to execute with ExecuteNonQuery.
https://msdn.microsoft.com/en-us/library/ms173492.aspx
https://msdn.microsoft.com/en-us/library/ms176118.aspx

Step to add new column in production server (SQL Server 2008)?

I am using a SQL Server 2008 database.
My project is live. Now I want to add a new column in my employee table.
How can I do that?
Please tell me the idea
Thanks.
There's a whole lot to consider there. Just off the top of my head:
Verify anything that accesses that table will not be negatively impacted. If anything is using SELECT * it is likely to blow up. Similarly, anything that selects from, or inserts into the DB by column index will need to be changed
Changing a column can require a drop/recreate of the table- make sure that no one will be accessing the table when you're making the change. This includes scheduled jobs, triggers, etc.
Make sure your back-ups are up to date. If something goes wrong, you want to be able to get back to where you were.
All in all, I'd say your best bet- if the option is available- is to follow these steps in a Development, and then in a QA environment to make sure you are as certain as possible about anything that will be impacted by the change so you can make the necessary adjustments.
Once you're sure about what you're doing, ALTER TABLE is the command you want, and Microsoft has plenty of documentation about how to use it. Alternatively, the SQL Server Management Studio gives a GUI for making the changes as well.
When adding a column to a table with data, the column should be NULL or you need a default value
ALTER TABLE myTable ADD AnotherColumn int NULL
or
ALTER TABLE myTable
ADD AnotherColumn int NOT NULL
CONSTRAINT DF_myTable _AnotherColumn DEFAULT 0
You use alter table
alter table YourTable add NewColumn int

Changing the column order/adding new column for 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. It is not allowing me to do without drop and recreate. But that is in production system and having data in that table. I can take backup of the data, and drop the existing table and change the order/add new columns and recreate it, insert the backup data into new table.
Is there any best way to do this without dropping and recreating. I think SQL Server 2005 will allow this process without dropping and recreating while changing to existing table structure.
Thanks
You can't really change the column order in a SQL Server 2008 table - it's also largely irrelevant (at least it should be, in the relational model).
With the visual designer in SQL Server Management Studio, as soon as you make too big a change, the only reliable way to do this for SSMS is to re-create the table in the new format, copy the data over, and then drop the old table. There's really nothing you can do about this to change it.
What you can do at all times is add new columns to a table or drop existing columns from a table using SQL DDL statements:
ALTER TABLE dbo.YourTable
ADD NewColumn INT NOT NULL ........
ALTER TABLE dbo.YourTable
DROP COLUMN OldColumn
That'll work, but you won't be able to influence the column order. But again: for your normal operations, column order in a table is totally irrelevant - it's at best a cosmetic issue on your printouts or diagrams..... so why are you so fixated on a specific column order??
There is a way to do it by updating SQL server system table:
1) Connect to SQL server in DAC mode
2) Run queries that will update columns order:
update syscolumns
set colorder = 3
where name='column2'
But this way is not reccomended, because you can destroy something in DB.
One possibility would be to not bother about reordering the columns in the table and simply modify it by add the columns. Then, create a view which has the columns in the order you want -- assuming that the order is truly important. The view can be easily changed to reflect any ordering that you want. Since I can't imagine that the order would be important for programmatic applications, the view should suffice for those manual queries where it might be important.
As the other posters have said, there is no way without re-writing the table (but SSMS will generate scripts which do that for you).
If you are still in design/development, I certainly advise making the column order logical - nothing worse than having a newly added column become part of a multi-column primary key and having it no where near the other columns! But you'll have to re-create the table.
One time I used a 3rd party system which always sorted their columns in alphabetical order. This was great for finding columns in their system, but whenever they revved their software, our procedures and views became invalid. This was in an older version of SQL Server, though. I think since 2000, I haven't seen much problem with incorrect column order. When Access used to link to SQL tables, I believe it locked in the column definitions at time of table linking, which obviously has problems with almost any table definition changes.
I think the simplest way would be re-create the table the way you want it with a different name and then copy the data over from the existing table, drop it, and re-name the new table.
Would it perhaps be possible to script the table with all its data.
Do an edit on the script file in something like notepad++
Thus recreating the table with the new columns but the same.
Just a suggestion, but it might take a while to accomplish this.
Unless you write yourself a small little c# application that can work with the file and apply rules to it.
If only notepadd++ supported a find and move operation

Forcing Management Studio to use ALTER TABLE instead of DROP/CREATE

I'm wondering if is there a way to force MSSQL Management Studio to produce a script like this:
ALTER TABLE Mytable
ADD MyCol bit NOT NULL
CONSTRAINT MyColDefault
DEFAULT 0 WITH VALUES
ALTER TABLE [dbo].Mytable
ALTER COLUMN MyCol2 int NULL
GO
when I alter a very simple property of a column on a table.
If I do this in the designer and ask for the produced script, the script doesn't do such simple tasks, but instead copies all the data in a tmp table, drops the original table, renames the tmp table with the original table name. And, of course, drops and recreates every constraint and relationships.
Is there any option I can change to change this behaviour? Or, this may be possible, is there some danger I don't see in using the simple ALTER TABLE above?
thanks.
Yes you can!
In SQL Server Management Studio, go into the table design mode for the table in question, and make your changes. However: do not click on the "Save" button, but instead right-click in the table design view, there should be a "Generate Change Script" item at the end of your context menu.
Click on that menu item and you'll get presented a pop-up dialog box which contains the T-SQL script needed to do those changes that you made to the table in the designer. Copy or save that T-SQL code, and cancel out of the designer, and voila - you have your change script!
UPDATE: Marco, sorry, I don't think there's any option to change the default behavior, at least not right now. You might want to file an enhancement request with Microsoft on Microsoft Connect to propose that - good idea, I would think!
You can't change the behaviour, it's just that the default script it creates is not always the most efficient. It creates scripts in a format it knows will work, although frequently the results will be slow and resource-heavy. I recommend you get used to creating the script for all changes yourself as you can better optimize it. There's nothing wrong with what you've created (providing you have no existing constraints/dependencies on MyCol2 that would be invalidated by it becoming a nullable int)
Just to augment #marc_s's answer. In case you still can't generate the change script 'cause your table needs to be recreated, you need to go to Tools -> Options and under Designers -> Table and Database Designers unmark the option Prevent saving changes that require table re-creation.
easy! just go to Tool->Option, then the Designer node and select Table and Database designer so that you can uncheck the Prevent saving changes that require ... checkbox.
Now you can make any chage on your tables design!

Resources