Postgresql: Violates check constraint. Failing row contains - sql

I tried to insert some data in a database with postgresql but still showing the same message:
ERROR: new row for relation "empleados" violates check constraint
"ck_empleados_documento" DETAIL: Failing row contains (13, 22222222,
f, Lopez, Ana, Colon 123, 1, 2, casado , 1990-10-10).
I do not know where or what the error is nor did I find anything that solved this. This is what i try to insert:
insert into empleados (documento, sexo, apellido, nombre, domicilio, idSecc, cantidadhijos, estadocivil, fechaingreso) values('22222222','f','Lopez','Ana','Colon 123',1,2,'casado','1990-10-10');
and this is the structure of the table:
CREATE TABLE public.empleados
(
idempleado integer NOT NULL DEFAULT nextval('empleados_idempleado_seq'::regclass),
documento character(8),
sexo character(1),
apellido character varying(20),
nombre character varying(20),
domicilio character varying(30),
idsecc smallint NOT NULL,
cantidadhijos smallint,
estadocivil character(10),
fechaingreso date,
CONSTRAINT pk_empleados PRIMARY KEY (idempleado),
CONSTRAINT fk_empleados_idsecc FOREIGN KEY (idsecc)
REFERENCES public.puestos (idpuesto) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION,
CONSTRAINT uq_empleados_documento UNIQUE (documento),
CONSTRAINT ck_empleados_documento CHECK (documento ~~ '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'::text),
CONSTRAINT ck_empleados_estadocivil CHECK (estadocivil = ANY (ARRAY['casado'::bpchar, 'divorciado'::bpchar, 'soltero'::bpchar, 'viudo'::bpchar])),
CONSTRAINT ck_empleados_hijos CHECK (cantidadhijos >= 0),
CONSTRAINT ck_empleados_sexo CHECK (sexo = ANY (ARRAY['f'::bpchar, 'm'::bpchar]))
)

The error message says your row violates check constraint "ck_empleados_documento".
ck_empleados_documento is defined as
CONSTRAINT ck_empleados_documento CHECK (documento ~~ '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'::text)
According to https://www.postgresql.org/docs/current/static/functions-matching.html#FUNCTIONS-LIKE:
The operator ~~ is equivalent to LIKE
So your constraint really means
documento LIKE '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'::text
From the same page:
stringLIKEpattern
If pattern does not contain percent signs or underscores, then the pattern only represents the string itself
Your pattern doesn't contain % or _, so it is equivalent to
documento = '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
This can never be true because documento is only 8 characters long.
You probably want to do this instead:
documento SIMILAR TO '[0-9]{8}'
SIMILAR TO uses SQL regexes and understands character classes such as [0-9].

I think your ck_empleados_documento should be written like this:
CONSTRAINT ck_empleados_documento CHECK (documento ~ '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'::text),
Explanation: According to the Postgres Documentation:
The operator ~~ is equivalent to LIKE
If you want pattern matching you need to use Operators:
~ Matches regular expression, case sensitive
~* Matches regular expression, case insensitive
!~ Does not match regular expression, case sensitive
!~* Does not match regular expression, case insensitive

This answer is for those who get this error even when they haven't explicitly defined any constraint. In my case I'm using django and one of my models has a field defined as a PositiveBigIntegerField, so the error occurred when some logic tried to set the field's value to a negative number. So check your model/table definitions to make sure you're not violating implicit constraints that exist without your knowledge.

Related

CHECK with ^[A-Z]{3}[0-9]{6}$ - SQL Server

CREATE TABLE PARTICIPANTE(
pasaporte NVARCHAR(9) NOT NULL,
nombre NVARCHAR(50) NOT NULL,
sexo CHAR(1) NOT NULL,
fecNac DATE NOT NULL,
codPais NVARCHAR(3) NOT NULL,
CONSTRAINT PK_PARTICIPANTE PRIMARY KEY (pasaporte),
CONSTRAINT FK_PAIS_PARTICIPANTE FOREIGN KEY (codPais) REFERENCES PAIS(codigo),
CONSTRAINT CHK_PASAPORTE CHECK (pasaporte like '^\[A-Z\]{3}\[0-9\]{6}$')
)
The CONSTRAINT CHK_PASAPORTE doesn't work when I try to insert the data.
The INSERT statement conflicted with the CHECK constraint "CHK_PASAPORTE". The conflict occurred in database "OMA", table "dbo.PARTICIPANTE", column 'pasaporte'.
Example
insert into PARTICIPANTE (pasaporte,nombre,sexo,fecNac,codPais) value ('JPN865653','Noguchi','F','20000104','JPN');
Can someone explain to me why this doesn't work and how can I fix it?
As I mention in the comments, SQL Server has no (in built) support for Regex, it only has basic pattern matching, which is explained in the documentation.
Fortunately, the logic you are after appears to be quite simple; 3 letters followed by 6 digits. This can be achieved with the following constraint:
ALTER TABLE dbo.PARTICIPANTE ADD CONSTRAINT CHK_PASAPORTE CHECK (pasaporte LIKE '[A-Z][A-Z][A-Z][0-9][0-9][0-9][0-9][0-9][0-9]');
Note that if you require the value to only contain uppercase values, you'll need to COLLATE the value to a collation that is case sensitive and orders upper case letters first, then lowercase, and finally alphabetically (Binary collations are one such one that does this).

How to prevent a input of certain letters using Oracle

The code is the category of the video, it is represented by one upper case character, excluding I, O,
Q, V, Y and Z, followed by a numeric character.
So far, I took a guess and got this. Any suggestions on how to fix it?
create table channelTable (
channelID number NOT NULL,
ChannelName varchar(100) NOT NULL,
ChannelDate date NOT NULL,
UserName varchar(100) NOT NULL UNIQUE,
TopicCode varchar(4) NOT NULL);
CONSTRAINT channelID_pk PRIMARY KEY (channelID)
CONSTRAINT c_topicCode LIKE '[A-Za-z][0-9] NOT (I,O,Q,N,Y,Z)
);
Some comments:
NOT NULL is not needed for PRIMARY KEY columns.
In Oracle, use VARCHAR2().
Then, I would suggests regular expressions. If the value is supposed to be exactly two characters, then declare it as such:
create table channelTable (
channelID number,
ChannelName varchar(100) NOT NULL,
ChannelDate date NOT NULL,
UserName varchar2(100) NOT NULL UNIQUE,
TopicCode char(2) NOT NULL;
CONSTRAINT channelID_pk PRIMARY KEY (channelID)
CONSTRAINT check (REGEXP_LIKE(c_topicCode, '^[A-HJ-NPR-UYZ][0-9]$')
);
Or perhaps more simply:
CONSTRAINT REGEXP_LIKE(c_topicCode, '^[A-Z][0-9]$') AND NOT REGEXP_LIKE(c_topicCode, '^[IOQNYZ]'))
All that said, I would rather see a table of TopicCodes that is populated with the correct values. Then you can just use a foreign key relationship to define the appropriate codes.
Use the regular expression ^[A-HJ-MPR-X]\d$ to match an upper-case character excluding I,O,Q,N,Y,Z followed by a digit:
CREATE TABLE channels (
id number CONSTRAINT channel__id__pk PRIMARY KEY,
Name varchar(100) CONSTRAINT channel__name__nn NOT NULL,
DateTime date CONSTRAINT channel__date__nn NOT NULL,
UserName varchar(100) CONSTRAINT channel__username__NN NOT NULL
CONSTRAINT channel__username__U UNIQUE,
TopicCode varchar(4),
CONSTRAINT channel__topiccode__chk CHECK ( REGEXP_LIKE( topiccode, '^[A-HJ-MPR-X]\d$' ) )
);
db<>fiddle
Also, you don't need to call the table channeltable just call it channels and you don't need to prefix the column names with the table name and you can name all the constraints (rather than relying on system generated constraint names which makes it much harder to track down issues when you are debugging).
Consider the following check constrait:
create table channelTable (
...
topicCode varchar(4) not null
check(
substr(c_topicCode, 1, 1) not in ('I', 'O', 'Q', 'V', 'Y', 'Z')
and regexp_like(topicCode, '^[A-Z]\d')
),
...
);
The first condition ensures that the code does not start with one of the forbidden characters, the second valides that it stats with an upper alphabetic character, followed by a number.
To avoid using two conditions, an alternative would be to list all allowed characters in the first position:
check(regexp_like(topicCode, '^[ABCDEFGHJKLMNPRSTUVWX]\d'))
This works in Oracle, and in very recent versions of MySQL.

Regular expression in Oracle DB

I'm trying to use REGEXP_LIKE in my table to check if the score of the game has the pattern:
(1 or 2 numbers)x(1 or 2 numbers)
My attempt was to use this expression
CONSTRAINT CK_PLACAR CHECK (REGEXP_LIKE (PLACAR, '^[[:digit:]]+x[[:digit:]]+$', 'i'))
But I'm not able to insert a score like '1x0'. I also tried some other options, like:
CONSTRAINT CK_PLACAR CHECK (REGEXP_LIKE (PLACAR, '^[[:digit:]]{1,2}x[[:digit:]]{1,2}$', 'i'));
CONSTRAINT CK_PLACAR CHECK (REGEXP_LIKE (PLACAR, '^[[:digit:]]*[[:digit:]]x[[:digit:]][[:digit:]]*$', 'i'));
I tried to change [[:digit:]] to [0-9] as well, but it didn't work either.
Here is my complete table:
CREATE TABLE PARTIDA (
TIME1 VARCHAR2(50) NOT NULL,
TIME2 VARCHAR2(50) NOT NULL,
DATA DATE NOT NULL,
PLACAR CHAR(5) DEFAULT '0x0',
LOCAL VARCHAR2(50) NOT NULL,
CONSTRAINT PK_PARTIDA PRIMARY KEY (TIME1, TIME2, DATA),
CONSTRAINT FK_PARTIDA FOREIGN KEY (TIME1, TIME2) REFERENCES JOGA(TIME1, TIME2),
CONSTRAINT CK_PLACAR CHECK (REGEXP_LIKE (PLACAR, '^[[:digit:]]+x[[:digit:]]+$', 'i'))
);
Here is my test case:
INSERT INTO PARTIDA VALUES ('TIME1', 'TIME2', SYSDATE, '1x0', 'ESTADIO1');
Here is the output:
Error starting at line : 1 in command -
INSERT INTO PARTIDA VALUES ('TIME1', 'TIME2', SYSDATE, '1x0', 'ESTADIO1')
Error report -
ORA-02290: check constraint (K9012931.CK_PLACAR) violated
Try '^\d{1,2}x\d{1,2}$' for at least 1 but not more than 2 digits on either side of the 'x'.
Maybe it's the syntax? Try this:
ALTER TABLE score_table ADD (
CONSTRAINT CK_PLACAR
CHECK (REGEXP_LIKE (PLACAR, '^\d{1,2}x\d{1,2}$', 'i'))
ENABLE VALIDATE);
EDIT thanks to kfinity's comment above. With PLACAR having a datatype of CHAR(5), that's a fixed-width datatype so if the data entered is less than 5 characters it gets padded with spaces causing it to not match the regex pattern. Either change the datatype to VARCHAR2(5) which is variable width and preferred, or change the regex to allow for possible zero or more spaces at the end:
'^\d{1,2}x\d{1,2} *$'
Just like Gary W's answer, you can also modify it to not accept scores like '0x' (01, 02, 03, ...) but accept 0 or simply 1, 2, 3 etc.
^(?!0\d)\d{1,2}x(?!0\d)\d{1,2}$

How to name NOT NULL constraint in CREATE TABLE query

For a test tomorrow we're told to name our constraints
I know it's possible to create a constraint when you use ALTER TABLE
but can you add a name to a not null constraint when you CREATE TABLE?
f.e.
CREATE TABLE test (
test1 VARCHAR
CONSTRAINT nn_test1 NOT NULL (test1)
)
I get an error when trying to run this query. Am I writing it wrong?
The error I get is
ERROR: syntax error at or near "NOT"
LINE 3: CONSTRAINT nn_test1 NOT NULL (test1))
^
SQL state: 42601
Character: 56
You have two options to define a named not null constraint:
Inline with the column:
CREATE TABLE test
(
test1 VARCHAR CONSTRAINT nn_test1 NOT NULL,
test2 integer --<< no comma because it's the last column
);
Or at the end of columns as an out-of-line constraint. But then you need a check constraint:
CREATE TABLE test
(
test1 VARCHAR,
test2 integer, --<< comma required after the last column
constraint nn_test1 check (test1 is not null)
);
This has become irrelevant, since you're not using SQL Server
First of all, you should always specify a length for a VARCHAR. Not doing so (in SQL Server variables, or parameters) may result in a string of just exactly ONE character in length - typically NOT what you want.
Then, you need to just specify the NOT NULL - there's no need to repeat the column name (actually this is the error) - if you're specifying the CONSTRAINT "inline" with the column definition (which is a perfectly legal and in my opinion the preferred way of doing this).
Try this code:
CREATE TABLE test
(
test1 VARCHAR(50)
CONSTRAINT nn_test1 NOT NULL
)
At least this is the CREATE TABLE statement that works in T-SQL / SQL Server - not sure about PostgreSQL (don't know it well enough, don't have it at hand to test right now).
I, a_horse_with_no_name, the two syntax:
constraint nn_test1 check (test1 is not null)
and
test1 VARCHAR CONSTRAINT nn_test1 NOT NULL
are equivalent ? performance correctly ecc.
Because in first case the SQL server exception return the name nn_test so the system know exactly error.

PostgreSQL CHECK Constraint with 'LIKE' fails but succeeds with 'SIMILAR TO' and/or POSIX '!~*'

I am using PostgreSQL 10.1.
I create the following table:
CREATE TABLE country
(
id smallint NOT NULL,
alpha2 character varying(2) NOT NULL,
alpha3 character varying(3) NOT NULL,
name character varying(38) NOT NULL,
CONSTRAINT country_pkey PRIMARY KEY (id),
CONSTRAINT country_alpha2_key UNIQUE (alpha2),
CONSTRAINT country_alpha3_key UNIQUE (alpha3),
CONSTRAINT country_name_key UNIQUE (name),
CONSTRAINT country_alpha2_check
CHECK ((char_length(alpha2::text)) = 2 AND
(alpha2 NOT LIKE '%[^a-zA-Z]%')),
CONSTRAINT country_alpha3_check
CHECK ((char_length(alpha3::text)) = 3 AND
(alpha3 NOT LIKE '%[^a-zA-Z]%')),
CONSTRAINT country_name_check CHECK (char_length(name::text) > 0)
);
Unfortunately, the following statement succeeds although it should not:
INSERT INTO country (id, alpha2, alpha3, name)
VALUES (1, '11', '111', 'Haiti');
If I substitute LIKE with SIMILAR TO then the above statement fails as it should.
If I substitute NOT LIKE '%[^a-zA-Z]%' with POSIX Regex !~* '[^a-zA-Z]' then the above statement does fail, too, as it should.
Is there any explanation why LIKE fails? Most of the examples I have seen use LIKE! It seems that LIKE doesn't like to work!
Tia
The explanation is obvious and is hidden in a mere technicality:
LIKE in PostgreSQL uses only two characters to form a pattern: underscore _ and percent sign %.