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

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

Related

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')

Alter table add column as select statement

How to do something like this...
alter table customer_schedule add (week_number as (TO_CHAR((SCHEDULE_DATE),'iw'))
Wherein SCHEDULE_DATE is one of the existing columns in table
This is where you need VIRTUAL COLUMN. If you are on 11g and up, you could certainly do -
alter table table_name
add (column_name [data_type] [generated always] as (column_expression) [virtual]);
In your case, it will be something like -
alter table customer_schedule add (week_number data_type generated always as (TO_CHAR((SCHEDULE_DATE),'iw') VIRTUAL)
On 9i, you cannot use virtual columns, so I'd probably go with a view:
create view customer_schedule_view as
select
c.*,
to_char(c.schedule_date, 'iw')) week_number
from
customer_schedule c;
Of course, in your forms you need then to select from the view rather from the table.
The default keyword is supposed to let you store values when there is some value missing, but due to restrictions, you cannot use a column name
A DEFAULT expression cannot contain references to PL/SQL functions or to other columns, the pseudocolumns LEVEL, PRIOR, and ROWNUM, or date constants that are not fully specified.
I think a row-level BEFORE INSERT/UPDATE trigger should do want you want to do.

Common methods for doing select with computation by need?

I would like to be able to add columns to a table with cells who's values are computed by need at 'querytime' when (possibly) selecting over them.
Are there some established ways of doing this?
EDIT: Okay I can do without the 'add columns'. What I want is to make a select query which searches some (if they exist) rows with all needed values computed (some function) and also fills in some of the rows which does not have all needed values computed. So each query would do it's part in extending the data a bit.
(Some columns would start out as null values or similar)
I guess I'll do the extending part first and the query after
You use select expression, especially if you don't plan to store the calculation results, or they are dependant on more than one table. An example, as simple as it could be:
SELECT id, (id+1) as next_id FROM table;
What type of database are you asking for? If it is SQL Server then you can use the computed columns by using the AS syntax.
Eg:
create table Test
(
Id int identity(1,1),
col1 varchar(2) default 'NO',
col2 as col1 + ' - Why?'
)
go
insert into Test
default values
go
select * from Test
drop table Test
In the SQL world it's usually expensive to add a column to an existing table so I'd advise against it. Maybe you can manage with something like this:
SELECT OrderID,
ProductID,
UnitPrice*Quantity AS "Regular Price",
UnitPrice*Quantity-UnitPrice*Quantity*Discount AS "Price After Discount"
FROM order_details;
If you really insist on adding a new column, you could go for something like (not tested):
ALTER TABLE order_details ADD column_name datatype
UPDATE order_details SET column_name = UnitPrice+1
You basically ALTER TABLE to add the new column, then perform an UPDATE operation on all the table to set the value of the newly added column.

Find columns with NULL values in Teradata

I would like to find the columns in a table that has a null value in it.
Is there a system table that have that information?
To find columns where "null" values are allowed try...
select *
from dbc.columns
where databasename = 'your_db_name'
and tablename = 'your_table_name'
and Nullable = 'Y'
then to identify the specific rows w/ null values, take the "ColumnName" from the previous result set and run queries to identify results... perhaps throw them in a volatile table if you want to take further action on them (update,delete).
-- for example you found out that column "foo" is nullable...
create volatile table isnull_foo_col
as
(
sel *
from your_table_name
where foo is null
) with data
on commit preserve rows;
If you have statistics collected on the column you can use the views found here for Teradata 12.0.03+ and Teradata 13.0.02+ to determine the number of records in the table that have NULL values.
In Teradata 14, if you use the SHOW STATISTICS with the VALUES clause you will get similar information generated by the views listed at the link above.
You can use the DBC.Columns data dictionary view to determine what columns in a particular table are nullable.

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

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.