Reputation: 2820
I have the following column in a database table:
FieldA (decimal(19, 2), not null)
Applying the following change:
ALTER TABLE dbo.MyTable
ADD
Field1 AS FieldA,
Field2 AS CONVERT(decimal(19,2), FieldA),
Field3 AS CAST(FieldA AS decimal(19, 2))
Gives me the following new columns:
Field1 (Computed, decimal(19, 2), not null)
Field2 (Computed, decimal(19, 2), null)
Field3 (Computed, decimal(19, 2), null)
Why are Field2
and Field3
nullable? How to make either of them non-nullable?
Please do note that FieldA
in Field2
and Field3
will be replaced with some computation on FieldA
, thus need to use either CONVERT()
or CAST()
to force the type of the result.
Upvotes: 0
Views: 522
Reputation: 82514
While I like HoneyBadger's answer, I want to offer another possibility:
Mark the computed columns as persisted not null. (non persisted computed columns does not support the not null
constraint)
This means that instead of being computed on demand (meaning, only when they are used in a select statement), the computed columns will be physically stored with the rest of the table's columns - and only gets computed when the value they rely on changes.
Persisted computed columns can only rely on constants, columns and deterministic functions - but convert
and cast
are deterministic, so no problem there:
CREATE TABLE dbo.MyTable
(
FieldA decimal(19, 2) not null
);
GO
ALTER TABLE dbo.MyTable
ADD
Field1 AS FieldA,
Field2 AS CONVERT(decimal(19,2), FieldA) PERSISTED NOT NULL,
Field3 AS CAST(FieldA AS decimal(19, 2)) PERSISTED NOT NULL;
GO
SELECT Column_Name, Is_Nullable
FROM Information_schema.Columns
WHERE Table_Name = 'MyTable'
Results:
Column_Name Is_Nullable
FieldA NO
Field1 NO
Field2 NO
Field3 NO
Upvotes: 1
Reputation: 15150
@RaduGheorghiu Explained in their comment why the attributes are nullable. Now, to make them not nullable, I wrote this little test:
DROP TABLE IF EXISTS dbo.test
GO
CREATE TABLE dbo.test (id INT NOT NULL)
GO
ALTER TABLE dbo.test ADD
field1 AS id
, field2 AS CONVERT(DECIMAL(5,2), id)
, field3 AS ISNULL(CONVERT(DECIMAL(5,2), id), 0.0)
, field4 AS COALESCE(CONVERT(DECIMAL(5,2), id), 0.0)
, field5 AS CASE WHEN id IS NOT NULL THEN CONVERT(DECIMAL(5,2), id)
ELSE 0
END
GO
This produces the following table:
+-------------+-----------+-------------+
| COLUMN_NAME | DATA_TYPE | IS_NULLABLE |
+-------------+-----------+-------------+
| id | int | NO |
| field1 | int | NO |
| field2 | decimal | YES |
| field3 | decimal | NO |
| field4 | decimal | YES |
| field5 | decimal | YES |
+-------------+-----------+-------------+
So you can force nullability with ISNULL
, but, rather surprisingly, not with COALESCE
or a CASE
expression.
Upvotes: 1