Possible to assign a default value on a NULL against table column in sql - sql

I am wondering if there is a way that when creating a table that you can assign a default value to a column if the value is null.
I understand that you can use the syntax DEFAULT however this is only for when the value is absent. Is there a way similar to this that you can say when NULL it will add the default without using a trigger.
CREATE TABLE DBO.TESTS
(
TEST VARCHAR(100) DEFAULT(ISNULL('test',NULL)),
NUM INT
)
This is a test and the kind of thing i was looking at?
UPDATE:
Example input
INSERT INTO TESTS (TEST,NUM)
VALUES (NULL,1)
Where the "NULL" is i would like that to enter the value "test". But also if i was to do the following
INSERT INTO TESTS (NUM)
VALUES (1)
This would also enter the value of "test" into the column "TEST".
I hope this helps.

Yes, there is a way to do what you want. It is called a trigger. You would have to define a trigger that sets the value when a NULL is inserted into the column.
If you use an INSTEAD OF trigger, then you can still declare the column as NOT NULL. The trigger will take care of assigning a value so the constraint is not violated.
So, you can do this. Why you would want to do it is another question. Perhaps you are not familiar with the DEFAULT keyword that allows default values to be inserted using a VALUES() clause. This is explained in the documentation for INSERT.

You can add a default constraint to your table which will automatically add a set value for the column if the insert does not have a value for it:
CREATE TABLE DBO.TESTS
(
TEST VARCHAR(100),
NUM INT
)
ALTER TABLE [DBO].[TESTS] ADD CONSTRAINT [DF_TESTS_TEST] DEFAULT (N'default_value_goes_here') FOR [TEST]
INSERT INTO [DBO].[TESTS] VALUES (NULL, 1)
INSERT INTO [DBO].[TESTS] (num) VALUES (2)
Results
NULL 1
'default_value_goes_here' 2
If you want to check during an insert you can use COALESCE
DECLARE #insertValue VARCHAR(100)
SET #insertValue = NULL
INSERT INTO DBO.TESTS VALUES (COALESCE (#insertValue, 'defaultValue'), 1);

The bottom line is that the column should be non-nullable with a default value.
It's possible to replace null values with default values in a trigger for insert/update, but that doesn't make any sense - first because it means every update/insert will have to do that extra work, and second, because that would make it impossible to insert null to the column (unless the triggers are disabled) so why allow nulls in the first place? It's a mistake that will only be confusing for anyone attempting to use that table.
Think about it from the user side - when you send null to a nullable column, you expect it to be null, you don't expect it to contain a value.
If you run this insert statement:
INSERT INTO TESTS (TEST,NUM)
VALUES (NULL,1)
You expect the table to contain a row where Test is null and num = 1.
You do not expect the Test column to contain the default value.

When providing a value for a column, including NULL, that value will be used. NULL is still a value, just an unknown value. A DEFAULT value will only be used if no value is passed (which, as I just said, NULL is a value so doesn't count).
If you don't want a NULL in your table, then instead stop people supplying them by setting your column as NOT NULL:
CREATE TABLE dbo.TestTable (ID int, String varchar(100) NOT NULL DEFAULT 'test')
GO
--INSERT is successful, String has a value of 'test'
INSERT INTO dbo.TestTable (ID)
VALUES(1);
GO
--INSERT fails, String cannot have a value of NULL
INSERT INTO dbo.TestTable (ID,
String)
VALUES(2,NULL);
GO
SELECT *
FROM dbo.TestTable;
GO
DROP TABLE dbo.TestTable;
GO

Related

SQL Server Insert with no specified columns

I have a table with an auto-generated ID column (and that's all!)
CREATE TABLE [dbo].[EmailGroup](
[EmailGroupGuid] [uniqueidentifier] NOT NULL
CONSTRAINT [PK_EmailGroup] PRIMARY KEY CLUSTERED ([EmailGroupGuid] ASC)
) ON [PRIMARY]
ALTER TABLE [dbo].[EmailGroup]
ADD CONSTRAINT [DF_EmailGroup_EmailGroupGuid] DEFAULT (newsequentialid()) FOR [EmailGroupGuid]
I want to INSERT into this table and extract the generated ID. but, I can't work out if it's possible. It seems to complain about the lack of values/columns.
DECLARE #Id TABLE (Id UNIQUEIDENTIFIER)
INSERT INTO EmailGroup
OUTPUT inserted.EmailGroupID INTO #Id
Is there any way to do this? I mean I could add a dummy column to the table and easily do this:
INSERT INTO EmailGroup (Dummy)
OUTPUT inserted.EmailGroupID INTO #Id
VALUES (1)
however I don't really want to.
I could also specify my own ID and insert that, but again, I don't really want to.
Though I'm not sure why would you need such a table, the answer to your question is to use the keyword DEFAULT:
INSERT INTO EmailGroup (EmailGroupGuid)
OUTPUT inserted.EmailGroupGuid INTO #Id
VALUES(DEFAULT);
Another option is to use DEFAULT VALUES, as shown in Pawan Kumar's answer.
The key difference between these two options is that specifying the columns list and using the keyword default gives you more control.
It doesn't seem much when the table have a single column, but if you will add columns to the table, and want to insert specific values to them, using default values will no longer be a valid option.
From Microsoft Docs on INSERT (Transact-SQL):
DEFAULT
Forces the Database Engine to load the default value defined for a column.
If a default does not exist for the column and the column allows null values, NULL is inserted.
For a column defined with the timestamp data type, the next timestamp value is inserted.
DEFAULT is not valid for an identity column.
DEFAULT VALUES
Forces the new row to contain the default values defined for each column.
So as you can see, default is column based, while default values is row based.
Please use this.
CREATE TABLE [dbo].[EmailGroup]
(
[EmailGroupGuid] [uniqueidentifier] NOT NULL CONSTRAINT [PK_EmailGroup] PRIMARY KEY CLUSTERED ([EmailGroupGuid] ASC)
) ON [PRIMARY]
ALTER TABLE [dbo].[EmailGroup]
ADD CONSTRAINT [DF_EmailGroup_EmailGroupGuid] DEFAULT (newsequentialid()) FOR [EmailGroupGuid]
DECLARE #Id TABLE (Id UNIQUEIDENTIFIER)
INSERT INTO EmailGroup
OUTPUT inserted.EmailGroupGuid INTO #Id DEFAULT VALUES
SELECT * FROM #Id
last 3 OUTPUTs from my Laptop
--92832040-7D52-E811-B049-68F728AE8695
--2B6ADC5F-7D52-E811-B049-68F728AE8695
--0140AF66-7D52-E811-B049-68F728AE8695

Cannot insert the value NULL into column X, column X does not allow nulls. INSERT fails.

I'm new to SQL Server and I am getting this error "Cannot insert the value NULL into column 'Occupied', table 'DBProjectHamlet.dbo.tblGrave'; column does not allow nulls. INSERT fails. The statement has been terminated."
This is my code for the insert followed by the code to create the table
INSERT INTO tblGrave (GraveName)
SELECT Grave
FROM tblPlotsandOccupants
IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'tblGrave' AND TABLE_SCHEMA = 'dbo')
DROP TABLE dbo.tblGrave;
GO
CREATE TABLE tblGrave
(
GraveID INT IDENTITY (1,1),
GraveName VARCHAR(MAX) NULL,
GraveTypeID INT NOT NULL,
PlotID INT NOT NULL,
Occupied BIT NOT NULL
)
I'm not trying to insert anything into column Occupied, I don't know why this is happening or how to fix it. I just want to insert values into tblGrave (GraveName). Any help would be great.
Exactly! You aren't doing anything with Occupied and that is the problem. The column is specified to be NOT NULL but has no default value. You are not inserting a value, so it gets the default. The default default is NULL, and that is not allowed.
One simple solution is:
INSERT INTO tblGrave (GraveName, Occupied)
SELECT Grave, 0
FROM tblPlotsandOccupants;
This fixes your immediate problem, but will then you will get an error on PlotId.
A more robust solution would add a default value for the NOT NULL columns and declare the rest to be nullable (the default). Something like this:
CREATE TABLE tblGrave (
GraveID INT IDENTITY (1,1) PRIMARY KEY,
GraveName VARCHAR(MAX),
GraveTypeID,
PlotID INT,
Occupied BIT NOT NULL DEFAULT 0
);
When you created your table, you defined that column as "NOT NULL" rather than allowing it to be null.
You need to either allow "Occupied" to be null, set a default value, or define the value that you want upon inserting.
You can even set the value to be ' ' which is blank but isn't null.
EDIT
Note #Gordon's answer for sql examples.

How to insert null value to NOT NULL column using the DEFAULT Constraint

These is my example table definition:
CREATE TABLE [MyTable]
(
[ColumnName] [bit] NOT NULL
)
ALTER TABLE [MyTable] ADD DEFAULT ((0)) FOR [ColumnName]
I want to be able to pass a Null value to my stored procedure's #ColumnValue, something like:
#ColumnValue = null;
INSERT INTO [MyTable] ([ColumnName])
VALUES (#ColumnValue)
But I'm getting this error:
"Cannot insert the value NULL into column... INSERT fails with"
Why the DEFAULT constraints not working?
Solved:
as #J.D. Pace said: The default value will be inserted only if the value is not specified on the Insert statement.
so as #dotNET suggested, i have specified the default value in the INSERT query statement using the ISNULL:
ISNULL - The SQL Server ISNULL() function lets you return an alternative value when an expression is NULL:
#ColumnValue = null;
INSERT INTO [MyTable] (
[ColumnName]
)
VALUES (
ISNULL(#ColumnValue, 0)
)
A table with only one column of bit type with a default value seems to be a bad design. This stuff can almost certainly be stored in a different and better way. On the other hand, if there are other columns in the table that you didn't include in the post, just skip this particular column in your INSERT query and it will work fine. Lastly, you can specify the default value in your INSERT query too.

NULL constraint after attribute in CREATE TABLE?

I'm new to SQL and I'm trying to figure out what this NULL is doing. Here a simple example:
CREATE TABLE test (
bla VARCHAR NULL
);
So I tried to figure out wether this is set to be the default value, but it is null as default wether I put it there or not, right?
Also I wondered if it has to stay null (for whatever reason) but when I tried to insert a value it was possible anyway. So does it do anything?
From CREATE TABLE:
NULL
The column is allowed to contain null values. This is the default.
You could write:
INSERT INTO test(bla)
VALUES (NULL);
-- it holds NULL
INSERT INTO test(bla)
VALUES (default);
-- it holds NULL
INSERT INTO test(bla)
VALUES ('a');
-- it holds 'a'
You could also omit column:
CREATE TABLE test2(bla VARCHAR NULL, col2 INT NOT NULL);
INSERT INTO test2(col2) VALUES (1);
-- it contains NULL, 1
If you specify column as:
CREATE TABLE test(bla VARCHAR NOT NULL);
INSERT INTO test(bla) VALUES (NULL);
-- error
EDIT:
You don't have to specify NULL explicitly.
CREATE TABLE test(bla VARCHAR);
is the same as:
CREATE TABLE test (bla VARCHAR NULL);
You are parameterizing the column can be NULL

How to insert into a table that specifies a DEFAULT value for every column?

I have a table where all columns are auto-populated whenever an insertion happens:
CREATE TABLE …
(
ItemID INT NOT NULL IDENTITY(…),
DateCreated DATETIME2 NOT NULL DEFAULT GETDATE()
);
How do I write a SQL statement that inserts a new row into this table without having to manually provide any concrete values to insert?
(There is already a similar question, but it differs in that it's about a table with some non-DEFAULT columns for which a value must be manually provided.)
Use the DEFAULT VALUES option:
INSERT INTO IdentitySpecification
DEFAULT VALUES;