How to control nullability in SELECT INTO for literal-based columns
It looks like a definitive answer is here. Copying here:
Metadata is determined based on the source column and expressions used
in the SELECT list. Below are the rules:
Any expression that uses a built-in function like SUBSTRING, LEFT, RIGHT etc (except ISNULL) for example is considered as NULLable by the
engine. So if you use CAST(somecol as char(8)) then the expression is
NULLableLiterals, constants, global variables like @@DBTS, @@ERROR etc are considered non-NULLable since they return some value always
If expression is a column then nullability is derived from the source column metadata
So to make an expression or column in the SELECT list not null then use ISNULL around the column or expression.
So, it looks like you are safe to use your CAST expression.
Create not nullable column using SQL Server SELECT INTO
It's more simple then I thought:
CREATE TABLE SO_IN
(
RAW NVARCHAR(10) NOT NULL
) ;
GO
SELECT
RAW,
ISNULL(RTRIM(RAW),'') AS RTRIM,
LTRIM(RAW) AS LTRIM
INTO SO_OUT
FROM
SO_IN;
SELECT COLUMN_NAME, IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'SO_OUT'
Create a nullable column using SQL Server SELECT INTO?
Nullability is inherited from the source column.
You can lose or gain nullability with an expression:
Example (constant literals appear to be problematic - need a good NOOP function which can return NULL):
CREATE TABLE SO5465245_IN
(
a INT NOT NULL
,b INT NULL
) ;
GO
SELECT COALESCE(a, NULL) AS a
,ISNULL(b, 0) AS b
,COALESCE(10, NULL) AS c1
,COALESCE(ABS(10), NULL) AS c2
,CASE WHEN COALESCE(10, NULL) IS NOT NULL THEN COALESCE(10, NULL) ELSE NULL END AS c3
INTO SO5465245_OUT
FROM SO5465245_IN ;
GO
SELECT TABLE_NAME
,COLUMN_NAME
,IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE 'SO5465245%'
ORDER BY TABLE_NAME
,ORDINAL_POSITION ;
GO
DROP TABLE SO5465245_IN ;
GO
DROP TABLE SO5465245_OUT ;
GO
Setting not null when casting data during SELECT INTO
When creating a new column with SELECT INTO, you can coerce not-null by wrapping the CAST
expression in ISNULL
. The explict CAST
of the literal determines the data type returned by ISNULL
as well as the value inserted into the new column. This provides full control over the resultant column type, length, precision, and scale. Without the CAST
SQL Server will infer the data type and properties from the specified literal.
Examples:
ISNULL(CAST('' AS varchar(20)),'') AS varcharColumn
ISNULL(CAST(0 AS int),0) AS intColumn
In the case of an existing column, the source column data type and nullability is used by default. You can similarly coerce a different data type with CAST and/or use ISNULL to change the nullability to NOT NULL.
Examples:
ISNULL(CAST(varchar10Column AS varchar(20)),'') AS varcharColumn
ISNULL(intColumn,0) AS intColumn
SQL literal value that is alternative to NULL
You can use function CAST
to convert the format to VARCHAR
to be considered as string.
Is there a way to make a column's nullability depend on another column's nullability?
Assuming you are on SQL Server or something similar, you can do this with a CHECK
constraint on your table. (Unfortunately, MySQL parses but ignores CHECK
constraints, so you'd have to use a trigger for that platform.)
If the table already exists:
ALTER TABLE ADD CONSTRAINT CK_ExitDateReason
CHECK (
(ExitDate IS NULL AND ExitReason IS NULL)
OR (ExitDate IS NOT NULL AND ExitReason IS NOT NULL)
);
If you are creating the table yourself:
CREATE TABLE dbo.Exit (
...
, CONSTRAINT CK_ExitDateReason CHECK ...
);
Using a check constraint is preferable to using a trigger because:
- check constraints are more visible than triggers
- the constraint is part of the table definition, as opposed to code that is run separately, so it's logically cleaner
- I am willing to bet it is faster than a trigger too
Why would using column aliases in a select statement fill in null values with the column name?
In most SQL dialects, single quotes are used as string literals. So in your query:
select
A as column1,
'B 1' as column2,
'C 2' as column3
from {{ ref(`my_data`)}}
You are not selecting from the columns called B 1
and C 2
, you are selecting the string literals "B 1" and "C 2", which is why your result is what it is.
In Postgres-like databases, you should use double quotes for names with spaces in them:
select
A as column1,
"B 1" as column2,
"C 2" as column3
from {{ ref(`my_data`)}}
In MySQL-like dialects (including Google BigQuery), you should use backticks instead:
select
A as column1,
`B 1` as column2,
`C 2` as column3
from {{ ref(`my_data`)}}
Null Value Statement
In a CREATE TABLE, the NULL or NOT NULL here varchar(50) null
is a constraint that determines whether NULLs are allowed. NOT NULL means no.
When you inserted data, which statement did you run?
INSERT TABLE1 VALUES (Null, 1, First, Null)
or
INSERT TABLE1 VALUES ('Null', 1, First, 'Null')
- The first one uses the keyword NULL, inserts a NULL (not a null value: no such thing, arguably). No values is stored except in the NULL bitmap fields
- The second one has a string "null" and the characters N, U, L, L + 2 bytes for length are stored
When you run SELECT * FROM TABLE1
, client tools will show NULL.
To test whether you actually have NULLs or the string NULL, run this
SELECT ISNULL(name, 'fish'), ISNULL(date, GETDATE()) FROM TABLE1
For the SELECTs
--null symbols. No value stored
SELECT * FROM TABLE1 WHERE NAME IS NULL
--string null
SELECT * FROM TABLE1 WHERE NAME = 'NULL'
--empty string
SELECT * FROM TABLE1 WHERE NAME = ' '
Note: null symbol/value is not empty string. It has no value and won't compare. Even to itself.
As for your DBA, the code above with ISNULL will decide what is stored.
Edit: if you are storing null symbol/value, then your DBA should read up on "null bitmap"
Related Topics
Can't Connect to SQL 2012 Remotely by Ip and Named Instance
Orm or Something to Handle SQL Tables with an Order Column Efficiently
Oracle Unique Constraint Based on Column Value
Whats The Best Sqlite Data Type for a Long String
Select Data from Multiple Tables
Why Doesn't Oracle Allow Consecutive Newline Characters in Commands
How to Search for Names with Apostrophe in SQL Server
Does Sqlite Support Replication
Sql Order by on Multiple Column
Postgres Unique Multi-Column Index for Join Table
Is It Faster to Check If Length = 0 Than to Compare It to an Empty String
Indexed View Vs Indexes on Table
Oracle SQL Return True If Exists Question
How to Write SQL in a Migration in Rails
How to Access Latest Row for Each Individual Identifier
Schema, Owner for Objects in Ms Sql
Can a Stored Procedure Work with Two Different Databases? How About Two Servers