Syntax Difference in Table Alter/Add with and without a NULL - sql

I have a question, but let me first say that this is being performed on a database which I inherited and I am currently trying to improve the design on. Also the reason for the syntax is the fact that there are a lot of tables that the datatypes have been 'tweaked' by tech support people (/facepalm) causing lots of issues.
IF NOT EXISTS(Select *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'RXINFO'
AND TABLE_SCHEMA = N'scriptassist'
AND COLUMN_NAME = N'Price')
BEGIN
Alter Table [scriptassist].[RXINFO] Add [Price] FLOAT
Print 'Price Field nonexistant creating this field'
END
ELSE
BEGIN
If Not Exists(Select *
From Information_Schema.Columns
Where Table_Name = N'RXINFO'
And Table_Schema = N'scriptassist'
And Column_Name = N'Price'
And DATA_Type = N'FLOAT'
AND IsNull(CHARACTER_MAXIMUM_LENGTH, 0) = 0)
BEGIN
Alter Table [scriptassist].[RXINFO] Alter Column Price FLOAT
Print 'Price Field needed type updating'
END
END
Is what I am currently doing to determine if a column needs to be altered or added to a database. However even in the case of only having to add say 3-4 columns on a 500K-750K line database, where the table is about 100 columns wide, I'm estimating that this is taking anywhere from 15-20 minutes per column.
Things I have done to try to speed it up:
Removed the indexes before and then re-add after
Single user mode
ensured no connection to the database other than mine
I still don't feel like it should be taking as long as it is, so my question is do I need to explicitly add the NULL after the column type for this to work as fast as I think it should?

If you specifiy "NULL" or perhaps 'NOT NULL WITH DEFAULT 0.0" then only the schema will be updated and the rows in the table will not be altered, so the change will sub second for each table.
If the column is NULLable it doesn't have to be there so there is no need to update the rows when you alter the schema.
If the column is not NULLable without a default then when you ALTER the schema to add the column every row in the existing table will be updated to add a column with the default default value of 0.0. This is why your alters take minutes.
If you specify 'NOT NULL WITH DEFAULT' then the "DEFAULT" is added when the row is read so again there is no need to update the table rows.
In both cases the current INSERT/UPDATE SQL will work without any changes. If you add a "NOT NULL" column with no default then current update SQLs will bomb out unless you add in the price column. This could be good thing or a bad thing depending on what you want to achieve.

Related

How to set all table columns to NOT NULL at once?

Is this even possible, if so how? if not then I would be happy with a way that doesn't require typing each column name one by one. My use-case is that I create a table from a query and would like to make all columns NOT NULL because I later do ORM using Slick and it is a lot nicer to have all those column types not null (and therefore non Option[X]). This is static data so the column values will not be null and won't change either.
Unlike MySQL, Postgres doesn't figure out that the originating query columns are all NOT NULL already.
I'd like to avoid in my script adding the constraint one by one and be prone to breaking the solution whenever the query schema is changed i.e.
CREATE TABLE dentistry_procedure AS SELECT * FROM ...
ALTER TABLE dentistry_procedure ALTER column * SET NOT NULL;
How?
You could use metadata table and build dynamic query:
SELECT format('ALTER TABLE %I '||STRING_AGG(format('ALTER COLUMN %I SET NOT NULL', COLUMN_NAME),CHR(13)||',')
, MIN(TABLE_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE IS_NULLABLE = 'YES'
AND TABLE_NAME = 't';
db<>Fiddle demo

SQL update records with join table

Currently I need to move three columns from table A to table B. And I am using the update join table script to copy the existing data to the new columns. Afterwards the old column at table A will be drop.
Alter table NewB add columnA integer
Alter table NewB add columnB integer
Update NewB
Set NewB.columnA = OldA.columnA, NewB.columnB = OldA.columnB
From NewB
Join OldA on NewB.ID = OldA.ID
Alter table OldA drop column columnA
Alter table OldA drop column columnB
These script will add new columns and update the existing data from the old table to the newly created columns. Then remove the old columns.
But due to system structure, I will required to run SQL Script for more than one times to makes sure the database is up to date.
Although I did If (Columns Exist) Begin (Alter Add, Update, Alter Drop) End to ensure the existence of columns required. But when the script runs at the next time, it will hit error that says the columns was not found from the old table in the "update" query. Because the columns were dropped when the script run at the first time.
Is there other ways to solve?
you will not be able to update using join, But you can do like this :
Update NewB set NewB.columnA = (select OldA.columnA from OldA where NewB.ID = OldA.ID);
Update NewB set NewB.columnB = (select OldA.columnB from OldA where NewB.ID = OldA.ID);
I don't know which database you are using, in database there are some system tables, from where you can get whether the column does exist in table or not, like in oracle, All_TAB_COLUMNS contains the information of all the columns of tables, so you can hit that table like below :
select 1 from ALL_TAB_COLUMNS where TABLE_NAME='OldA' and COLUMN_NAME in ('columnA','columnB');
if resulting records are empty that means specified columns are not present in the table so you can skip your queries.
There must be something wrong with your is column exists check. I have similar DDL and DML operations many times. As you did not show how you are checking column existence I am not able to tell you what's wrong.
Anyway, you are adding a new column to a table. We can check if such column exists, if not - run the script, if yes- skip the script. And here is the check:
IF EXISTS(SELECT 1 FROM [sys].[columns] WHERE OBJECT_ID('[dbo].[NewB]') = [object_id] AND [name] = 'columnA')
BEGIN
BEGIN TRANSACTION;
....
COMMIT TRANSACTION;
END;

Efficiently add a column with a value

I am trying to add a column to a tsql table, i do this using SMO in c#. Altering the table is fine but i want to set the column to have a value. The table contains 650 million rows and the update query is taking over a day and a half to run.
Update [TempDatabase].[dbo].[table1] set RawSource = 'DTP'
This is the query I am running above.
Can anyone think of a more efficient way of doing this?
Thanks in advance.
Sometimes, it is more efficient to copy the table with the new value and re-create the table in a single command. Also, you might want to be sure that you have minimal logging for these operations.
Probably the best solution is to use a default value when you create the column:
alter table table1 add RawSource varchar(255) not null default 'DTP';
If you don't want the default moving forward, you can remove it after the column is added.
Another method uses computed columns, but basically does the same thing:
alter table table1 add _RawSource varchar(255);
alter table1 add RawSource as (coalesce(_RawSource, 'DTP'));
at the time of addition of column to table only we can set a default value which will applies for all rows
Note:U should keep not null compulsory because if not all rows are applicable with nulls
alter table table_name
add row_source nvarchar(5) not null default(N'DTP')

is there an easy to use formula for switching the datatype on a table column from int to bit?

I'm looking at a sql server table, and one of the columns seems to have been setup to be of type INT NULL when it's really better off as a BIT NOT NULL.
Is there an easy formula or shortcut for switching the type?
My current strategy is:
add new temp column
populate with data based on old column contents
drop old column and constraints
rename new column to old column name
add constraints based on new column
this seems complicated but, really, should be automatable - so i'm wondering if anyone's automated it yet.
Update MyTable set MyColumn = 0 where MyColumn is null
Assuming you want null to be false
Alter table MyTable alter column MyColumn bit not null
Will do the job, given all non-zero values are to be treated as true.
Course you were going to backup before you did any of this weren't you. :)

Altering more than one column in a table in oracle

Will the two scripts below (for altering a table) make diff..??
script 1 :
alter table ACNT_MGR_HSTRY add DM_BTNUMBER DATA_TYPE ;
alter table ACNT_MGR_HSTRY add DM_BTID DATA_TYPE ;
alter table ACNT_MGR_HSTRY add DM_USERID DATA_TYPE ;
alter table ACNT_MGR_HSTRY add DM_WSID DATA_TYPE ;
script 2 :
alter table ACNT_MGR_HSTRY
add
(
DM_BTNUMBER DATA_TYPE,
DM_BTID DATA_TYPE,
DM_USERID DATA_TYPE,
DM_WSID DATA_TYPE
);
will update makes a diff..???
update OPERATIONAL_UNIT
set ( BANK_ID=
ENTY_CODE_ID=
TIME_ZONE=
DM_BTNUMBER=
DM_BTID=
DM_USERID=
DM_WSID=
);
-----------
update OPERATIONAL_UNIT set BANK_ID=;
update OPERATIONAL_UNIT set ENTY_CODE_ID=;
update OPERATIONAL_UNIT set TIME_ZONE=;
update OPERATIONAL_UNIT set DM_BTNUMBER=;
update OPERATIONAL_UNIT set DM_BTID=;
update OPERATIONAL_UNIT set DM_USERID=;
update OPERATIONAL_UNIT set DM_WSID=;
The two examples are equivalent.
I've only ever used statements like you have in the first example; I don't know if it's possible that you won't get as good an error message if using the second example format in the event of an error.. Gary Myers confirmed my belief:
Mostly the same. If, for example, DM_WSID already existed then the relevant statement would fail. In script 1, you'd get three of the columns added. In script 2 you wouldn't. If you have DDL triggers or AUDIT, then they will get fired multiple times for case 1. Script 1 will commit multiple times and MAY wait for an exclusive table lock several times.
Script 2 will generally perform much better than script 1. Grouping similar changes and performing them all at once is almost always faster. But the real question is, is the difference significant?
Based on your comment about 50 tables with 15 columns each, I'd say the difference is at least somewhat significant, and possibly very significant depending on your configuration.
Just yesterday I made almost the exact same change, modifying about 30 columns for about 100 tables. Running the script locally using SQL*Plus, the time decreased from 2 minutes to 4 seconds. Most of the time was probably spent communicating between SQL*Plus and the database. If you have a SQL*Plus script that needs to be run remotely those round trips could make your script painfully slow.
One more way we can Modify our Columns by bracketing each column that we need to alter it .
Here The instance :-
Alter table news
modify (Newsid number primary key )
modify (newsArticleNo number check (newsArticleNo > 0))
modify (NewsArea char(15) default '' );