How to set default values properly in SQL? - sql

I have a table which should not have any NULL values at all. When I set a NOT NULL constraint, it disallows the statement and it fails with the constraint error. Default constraint will take place only if the column is not referenced in the insert statement.
How can we get around this? If a insert statement has a NULL value for any of the columns, then the DEFAULT value must be taken instead of the NULL values.
create table temp1 (col0 int, col1 int default 0);
insert into temp1 (col0) values (1); --> col0 -> 1 and col1 ->0
insert into temp1 (col0,col1) values (1,NULL); --> col0 -> 1 and col1 -> NULL (I would expect a 0 here instead of NULL)
alter table temp1 (add column col2 int not null default 0); --> col2 -> 0 for all the existing rows
insert into temp1 (col0) values (2); --> col0 -> 2 and col1 ->0 and col2-> 0
select * from temp1;
COL0 |COL1 |COL2
1 |0 |0
1 |(null) |0
2 |0 |0

Converting NULL into a column's default value for an insert is not part of standard SQL.
As you observed, you can omit the column from the insert statement but that is not the same as inserting a NULL value. Rather, in effect, the default value for a column's DEFAULT is NULL (SQL92 13.8 General Rules 4b); this is why inserting default values gives NULLs if there is no explicit default defined.
You can alternatively include the column and use the keyword DEFAULT (SQL92 7.1 General Rules 2). WX2 doesn't currently support this syntax but Kognitio plans to add it in the upcoming version 8.2.
insert into temp1 (col0, col1) values (1, DEFAULT);
The standard only allows you to use DEFAULT as shown above and not in a compound expression or in an insert-select statement.
-- NOT VALID IN STANDARD SQL!
insert into temp1 (col0, col1) values (1, case when ... then 1 else DEFAULT end);
-- NOT VALID IN STANDARD SQL!
insert into temp1 (col0, col1) select C1, DEFAULT from ...;
You can solve this using a COALESCE() function.
insert into temp1 (col0, col1) select E1, COALESCE(E2, 0) from ...;
Other databases don't in general allow converting NULLs to default values either: see similar questions for SQL Server, MySQL, Postgres and
Firebird. Oracle does have a non-standard syntax to create table columns with DEFAULT ON NULL which would do what you want.
(Kognitio might add DEFAULT in compound expressions or DEFAULT ON NULL as extensions in a future release.)

Related

INSERT row in table a for every row in table b [duplicate]

If I have an SQL table with all default columns (e.g. identity column + any number of columns all with default values), what is the SQL statement to insert a row with no explicit values given?
insert MyTable /* ( doh, no fields! ) */
-- values( doh, no values! )
What's the trick?
This is a part of the INSERT syntax
INSERT INTO TableName DEFAULT VALUES
Read more here:
https://learn.microsoft.com/en-us/sql/t-sql/statements/insert-transact-sql
You can use the DEFAULT keyword.
The accepted answer only works for one row, not for multiple rows.
Let us assume you know how many rows to insert, but you want all default values. You cannot do the following, for instance
INSERT MyTable
SELECT DEFAULT VALUES -- Incorrect syntax near the keyword 'DEFAULT'.
FROM SomeQueryOrView;
-- or
INSERT MyTable
DEFAULT VALUES -- Incorrect syntax near the keyword 'FROM'.
FROM SomeQueryOrView;
Instead we can hack MERGE to do this
MERGE INTO myTable
USING (SELECT SomeValue FROM SomeQueryOrView) s
ON 1 = 0 -- never match
WHEN NOT MATCHED THEN
INSERT DEFAULT VALUES;
A bonus benefit is that we can OUTPUT data from columns which are not being inserted:
MERGE INTO myTable
USING (SELECT SomeValue FROM SomeQueryOrView) s
ON 1 = 0 -- never match
WHEN NOT MATCHED THEN
INSERT DEFAULT VALUES
OUTPUT inserted.Id, s.SomeValue;

SQL not NULL(no default value) but allowed to insert NULL value

I have this table nonulls col1 varchar NULL col2 numeric (24,6) NOT NULL.
How can I insert value like this,
INSERT INTO nonulls (col1) SELECT 'ARF' as col1
Without having value for col2, some existing command in some of SSIS package here have that kind like of query but the col2 is not null but it still proceeds inserting value. Without using "coalesce" and without changing NOT NULL to "allow null".
If col2 has a default value, then you can insert a row with no value. It would be declared something like:
col2 <type> not null default <default value>
The default default value is NULL, which a not null declaration would preclude.
It is also possible that the table has an insert trigger defined on it. The trigger could assign a value to the column.

What means DEFAULT VALUES specification in an insert query?

I am pretty new in Microsoft SQL Server and I am not so into DB in general.
I have the following doubt about an insert query that begin in this way:
insert into MyTable DEFAULT VALUES
What exactly mean the DEFAULT VALUES specification?
Tnx
Andrea
Reading the fine manual yields:
DEFAULT VALUES
Forces the new row to contain the default values defined for each column.
Well it uses the default values specified in your table.
So for example if you have a column CreationDate datetime default(getdate()) it will use it.
If each of the required columns in MyTable has specified DEFAULT VALUE then this statement insert such a row.
For example you could have column Date with default 01/01/2014 and position with DEFAULT 'Developer' and this statement would insert such a record.
You can read more here: http://msdn.microsoft.com/en-us/library/aa933206%28SQL.80%29.aspx
You can watch default specifications in work by checking that code:
DECLARE #tmp as table
(
id int null,
num int null default(777),
txt varchar(10) null default('abc'),
date datetime null
)
insert into #tmp DEFAULT VALUES
select * from #tmp
Output is
id num txt date
NULL 777 abc NULL

TSQL Insert the column default value from Case Statement

I'd like to use the column's default value in an stored procedure insert, so that I don't have to repeat the default value in multiple places (it could change... DRY principle).
The T-SQL INSERT operation has a handy 'default' keyword that I can use as follows:
Declare #newA varchar(10)
Set #newA = 'Foo2'
-- I can use "default" like so...
Insert into Table_1 (
A,
B)
Values (
#newA,
default)
However, If I need to do something conditional, I can't seem to get the case statement to return 'default'.
-- How do I use 'default' in a case statement?
INSERT INTO Table_1 (
A,
B )
VALUES (
#newA,
CASE WHEN (#newA <> 'Foo2') THEN 'bar' ELSE default END)
-- > yeilds "Incorrect syntax near the keyword 'default'."
I could insert the default, and then update as needed like so:
INSERT INTO Table_1 (
A,
B )
VALUES (
#newA,
default)
UPDATE Table_1
SET B = CASE WHEN (A <> 'Foo2') THEN 'bar' ELSE B END
WHERE ID = SCOPE_IDENTITY()
But I'd really like somebody to tell me "There's a better way..."
Here's a table definition for this example if it helps...
CREATE TABLE dbo.Table_1 (
ID int NOT NULL IDENTITY (1, 1),
A varchar(10) NULL,
B varchar(10) NULL )
GO
ALTER TABLE dbo.Table_1 ADD CONSTRAINT DF_Table_1_A DEFAULT 'A-Def' FOR A
GO
ALTER TABLE dbo.Table_1 ADD CONSTRAINT DF_Table_1_B DEFAULT 'B-Def' FOR B
GO
default only works from within a VALUES() block, which does not seem to be an acceptable value in a CASE statement; you could use an if statement to determine what to insert:
DECLARE #newA varchar(10) = 'Foo2'
IF (#newA <> 'Foo2')
BEGIN
INSERT INTO Table_1 (A, B)
SELECT #newA, 'bar'
END
ELSE
BEGIN
--If you are using default values, you do not have to specify the column
INSERT INTO Table_1 (A)
SELECT #newA
END
I think this is better than updating after an insert, so that you only insert correct data into your table. It also keeps the number of INSERTS/UPDATES to 1. You should also be careful when you using ##IDENTITY due to scoping. Consider looking into SCOPE_IDENTITY().

SQL Server Concatenate string column value to 5 char long

Scenario:
I have a table1(col1 char(5)); A value in table1 may '001' or '01' or '1'.
Requirement:
Whatever value in col1, I need to retrive it in 5 char length concatenate with leading '0' to make it 5 char long.
Technique I applied:
select right(('00000' + col1),5) from table1;
I didn't see any reason, why it doesn't work? but it didn't.
Can anyone help me, how I can achieve the desired result?
Since you're using a fixed width column, it's already of size 5 (with whitespace). You need to trim it:
DECLARE #table1 TABLE (col1 char(5))
INSERT INTO #table1 (col1) VALUES ('12345')
INSERT INTO #table1 (col1) VALUES ('1')
SELECT RIGHT('00000'+RTRIM(col1),5) FROM #table1
-- Output:
-- 12345
-- 00001
Or use varchar instead:
DECLARE #table2 TABLE (col1 varchar(5))
INSERT INTO #table2 (col1) VALUES ('12345')
INSERT INTO #table2 (col1) VALUES ('1')
SELECT RIGHT('00000'+col1,5) FROM #table2
-- Output:
-- 12345
-- 00001
If you are storing the data in a CHAR field you are probably getting right spaces buffered with blanks. e.g. 01 = "01 ". If your do a RIGHT("00000" + value, 5) it'll still be the original value. You need to do a RTRIM() on the value or store the data in a VARCHAR field.
The problem is that the char(5) field is always 5 characters long, not matter what you put into it. If you insert '01' into the field, the value stored is actually '01 ' (note the trailing spaces).
Try this:
select right(('00000' + replace(col1, ' ', '')), 5)
Edit: I will leave my answer here as an example, but Michael's answer using rtrim is better.
you need to store your data in a consistent manner, so you don't need to write queries to format the data each time. this will fix your existing data:
UPDATE table1
SET col1= RIGHT('00000'+ISNULL(RTRIM(col1),''),5)
now every time you select you only have to do this:
SELECT col1 FROM table1
however, you must make sure that the data is formatted properly (leading zeros) every time it is inserted. I'd add a check constraint just to make sure:
ALTER TABLE table1 ADD CONSTRAINT
CK_table1_col1 CHECK (LEN(col1)=5)
and when you insert do this:
INSERT INTO table1
(col1, ...
VALUES
(RIGHT('00000'+ISNULL(RTRIM(#col1),''),5)