postgreSQL check constraint and null - postgresql

I created a table "TEST" and i tried to input some data however i got an error. The error is ERROR: new row for relation "test" violates check constraint "test_status_check" DETAIL: Failing row contains (5 , 2015-07-21, 15:00:00, I7 , 9 , NULL, NULL).
I think it is because of the null of the status. Therefore, i tried put a null in the test table but still not working
Create table test(
clientID CHAR (20),
startDate date,
startTime time,
instructorNO CHAR(20),
centreID CHAR(20),
status CHAR(4) CHECK (status IN ('Fail','Pass')) NULL,
reason VARCHAR(400),
omitted...
)
ERROR: new row for relation "test" violates check constraint "test_status_check" DETAIL: Failing row contains (5 , 2015-07-21, 15:00:00, I7 , 9 , NULL, NULL).

EDIT: I've completely changed my mind. Your existing code is valid (and the NULL part is unnecessary).
According to the documentation,
It should be noted that a check constraint is satisfied if the check expression evaluates to true or the null value. Since most expressions will evaluate to the null value if any operand is null, they will not prevent null values in the constrained columns. To ensure that a column does not contain null values, the not-null constraint described in the next section can be used.
So, something else is messed up. See here for an example of your original code working.

Related

Column name in error text: value too long for type character

We have a table with 2 columns (both have the same type and size) and 2 constraints for them:
create table colors
(
color varchar(6)
constraint color_check check
((color)::text ~ '^[0-9a-fA-F]{6}$'::text),
color_secodandry varchar(6)
constraint color_secondary_check check
((color_secodandry)::text ~ '^[0-9a-fA-F]{6}$'::text),
);
In case of inserts with long values:
insert into colors (color, color_secondary) values ('ccaabb', 'TOO_LONG_TEXT');
insert into colors (color, color_secondary) values ('TOO_LONG_TEXT', 'ccaabb');
we'll get the same errors for two error cases:
ERROR: value too long for type character varying(6) (SQLSTATE 22001)
PostgreSQL validates length for that columns before make inserts, so our checks never run. Is there a way to understand, which column has an invalid data?
The issue you are having is the order of evaluation for the intended values. You told Postgres to not allow a length over 6 (character varying(6)) you also specified additional certain criteria those values have to satisfy. What is happening is Postgres validates the length criteria and throws an exception when the value fails, in that case the check constraint is not preformed as Postgres works on an exit on first failure. The check constraint is processed only after the length passes. Example:
create table test1( id integer generated always as identity
, color6 character varying (6)
constraint color6_check check (color6 ~ '^[0-9a-fA-F]{6}$')
, color60 character varying (60)
constraint color60_check check (color60 ~ '^[0-9a-fA-F]{6}$')
) ;
insert into test1( color6 ) values ('aabbccdd') ;
/* Result
SQL Error [22001]: ERROR: value too long for type character varying(6)
ERROR: value too long for type character varying(6)
*/
insert into test1( color60 ) values ('aabbccdd') ;
/* Result
SQL Error [23514]: ERROR: new row for relation "test1" violates check constraint "color60_check"
Detail: Failing row contains (3, null, aabbccdd).
ERROR: new row for relation "test1" violates check constraint "color60_check"
*/
Notice the only difference between them is the length specification for the column being inserted. Yet they fail, but for a different reasons. Since both the length specification and the check constraint enforce the length you need to decide now how you want to handle the 2 conditions: a separate error for each condition or a single error for both. (IMHO: separate messages)

updating daterange with part of self

Allright this one is bugging me. Im not that versed in PostgreSQL yet, so it's probably a gap in my knowledge
Consider this:
insert into aaa (afdel_id, elev_id,periode,primaer_afd) select :AFD_ID, :ELEV_ID,
daterange(:PR_DATO, null, '[]'), true
ON CONFLICT ON CONSTRAINT afdel_elev_periode_ck
DO UPDATE SET primaer_afd = true, periode = daterange(least(lower(periode), :PR_DATO), null, '[]')
it gives me the error "column reference "periode" is ambiguous" propably due to this periode = daterange(least(lower(periode), :PR_DATO), null, '[]')
What I want to do is setting the lower part of the daterange [periode] to the first date of lower(periode) and :PR_DATO. (and just set any upper(periode) to null)
What am I missing?
You are using ON CONFLICT so you have access to different versions of a column when you do an UPDATE. The original version which is accessed as table_name.col_name and the proposed new value which is exclude.col_name. This is where the error is coming from. Postgres does not know which value you want to use for periode in daterange(least(lower(periode).
For more information see:
https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT
You need to prefix the column name with the table name to avoid the ambiguity
insert into aaa (afdel_id, elev_id,periode,primaer_afd)
select :AFD_ID, :ELEV_ID, daterange(:PR_DATO, null, '[]'), true
ON CONFLICT ON CONSTRAINT afdel_elev_periode_ck
DO UPDATE
SET primaer_afd = true,
periode = daterange(least(lower(aaa.periode), :PR_DATO), null, '[]')

POSTGRES COALESCE(NULLIF(c.name,''), 'unassigned') not working

No version of a character varying field will return anything but NULL if there isn't a value... it's really frustrating
CASE WHEN COALESCE(NULLIF(e.name,''),'unassigned') IS NULL THEN 'unassigned' ELSE a.name END
was my final test and it still simply returns NULL unless the field has a value
it's character varying(255)
COALESCE(a.name,'unassigned') // won't work
NULLIF(a.name,'') // won't work
NULLIF(a.name,NULL) // won't work
COALESCE(NULLIF(a.name,''),'unassigned') // won't work
however the instant i use 0 it works..
what's up with that?
it's a character varying(255) field and it is set to default to null
as a matter of point the build of the table column is
name varying character(255) DEFAULT(NULL)
so I know it's entering NULL
and I've already done a
SELECT * FROM <tbl> WHERE name IS NULL; and of course, I return all the NULL rows with a.name... so what's the deal with this?
ok... to everyone deciding to answer me with:
COALESCE(NULLIF(e.name,''),'unassigned') IS NULL...
This method will never work on a return of "no records" and as this is a stored procedure which creates a materialized view, where I'm polling via nested queries - where it is possible for a column to have 0 (as the default id = other_id) the nested query would simply return no rows. When no row is returned, the functions of COALESCE or NULLIF would never execute. A row would have to be returned in order for those functions to act upon the row values... As I've never heard of a table with a PK auto-incremented field starting at 0 and generally starting at 1 the resultset of "no records returned" will always return a NULL value into the materialized view column.
The query I run afterward to poll rows from that materialized view will however function properly as COALESCE(etc etc) because now there is an actual NULL value in that column.

T-SQL Replace part of a not null column with NULL generates error

I have table variable and all its columns can not be null (NOT NULL definition for each):
DECLARE #SampleTable
(
,SampleColumnID nvarchar(400) NOT NULL PRIMARY KEY
,SampleColumnText nvarchar(max) NOT NULL
)
I have done some operation with this variable and initialize the "SampleColumnText" with some text.
Then I try to replace some part of it with text return from other function. What happens is that the function returns NULL in some cases, so I this code generates me error:
REPLACE(SampleColumnText , '{*}', #InitByFunctionText)
WHERE #InitByFunctionText is NULL this time.
So, is it normal error to be generated as I am replacing only part of the text with NULL, not the whole text?
This is expected behaviour. REPLACE:
Returns NULL if any one of the arguments is NULL.
If you want to replace it with an empty string (which is not the same as NULL), you can use COALESCE:
REPLACE(SampleColumnText , '{*}', COALESCE(#InitByFunctionText,''))
I had a similar thing recently and the following got around this issue:
REPLACE(SampleColumnText , '{*}', ISNULL(#InitByFunctionText, ''))

an empty row with null-like values in not-null field

I'm using postgresql 9.0 beta 4.
After inserting a lot of data into a partitioned table, i found a weird thing. When I query the table, i can see an empty row with null-like values in 'not-null' fields.
That weird query result is like below.
689th row is empty. The first 3 fields, (stid, d, ticker), are composing primary key. So they should not be null. The query i used is this.
select * from st_daily2 where stid=267408 order by d
I can even do the group by on this data.
select stid, date_trunc('month', d) ym, count(*) from st_daily2
where stid=267408 group by stid, date_trunc('month', d)
The 'group by' results still has the empty row.
The 1st row is empty.
But if i query where 'stid' or 'd' is null, then it returns nothing.
Is this a bug of postgresql 9b4? Or some data corruption?
EDIT :
I added my table definition.
CREATE TABLE st_daily
(
stid integer NOT NULL,
d date NOT NULL,
ticker character varying(15) NOT NULL,
mp integer NOT NULL,
settlep double precision NOT NULL,
prft integer NOT NULL,
atr20 double precision NOT NULL,
upd timestamp with time zone,
ntrds double precision
)
WITH (
OIDS=FALSE
);
CREATE TABLE st_daily2
(
CONSTRAINT st_daily2_pk PRIMARY KEY (stid, d, ticker),
CONSTRAINT st_daily2_strgs_fk FOREIGN KEY (stid)
REFERENCES strgs (stid) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT st_daily2_ck CHECK (stid >= 200000 AND stid < 300000)
)
INHERITS (st_daily)
WITH (
OIDS=FALSE
);
The data in this table is simulation results. Multithreaded multiple simulation engines written in c# insert data into the database using Npgsql.
psql also shows the empty row.
You'd better leave a posting at http://www.postgresql.org/support/submitbug
Some questions:
Could you show use the table
definitions and constraints for the
partions?
How did you load your data?
You get the same result when using
another tool, like psql?
The answer to your problem may very well lie in your first sentence:
I'm using postgresql 9.0 beta 4.
Why would you do that? Upgrade to a stable release. Preferably the latest point-release of the current version.
This is 9.1.4 as of today.
I got to the same point: "what in the heck is that blank value?"
No, it's not a NULL, it's a -infinity.
To filter for such a row use:
WHERE
case when mytestcolumn = '-infinity'::timestamp or
mytestcolumn = 'infinity'::timestamp
then NULL else mytestcolumn end IS NULL
instead of:
WHERE mytestcolumn IS NULL