Sql constraint on boolean field - odoo

Is there is a possibility to make SQL constraint for the boolean field? I want to make a constraint that will check all record and only 1 record can have boolean field checked

Try using this,
_sql_constrainst =[('your const. id', 'check(your_bool_field != Null)', 'Your validation msg')]

Related

Postgresql: Violates check constraint. Failing row contains

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.

check constraint that references multiple columns in the same table

I am attempting to add a constraint to a DB2 database that will check three columns. I am using a table that is an invoice table that includes start date end date quantity item price etc. for each line item on an invoice. I want to prevent allowing start and end date from being null when a column linestatus = RELELASED. Here is the alter statement that I have so far. My question is why won't this work? I have verified that this table does not have any current instances of all three of these checks.
alter table pluspgbtrans
add constraint start_end_notnull
Check (eip_linestatus = 'RELEASED' AND eip_endate is not null AND eip_startdate is not null)
Your SQL statement is valid.
However, your logic has an error: this check does not apply only if eip_linestatus = 'RELEASED'.
As written, your constraint is asserting that all rows must have eip_linestatus = 'RELEASED' AND eip_endate is not null AND eip_startdate is not null.
So, if any rows in your table have eip_linestatus with a value of anything other than RELEASED, you'll get the SQL0544N error when you try to add the constraint.
To create the constraint you're looking for, you need to handle the other state(s) for eip_linestatus. I can't guess what they are, so here's a potential generic option:
alter table pluspgbtrans
add constraint start_end_notnull check (
(eip_linestatus <> 'RELEASED')
OR
(
eip_linestatus = 'RELEASED'
AND eip_endate is not null
AND eip_startdate is not null
)
);

Postgresql unable to change the data type of a column

I am new to Postgresql, and I am trying to change the data type of a column from Integer to Varchar(20), but I get strange error:
ERROR: operator does not exist: character varying <> integer :
No operator matches the given name and argument type(s).
You might need to add explicit type casts.********** Error **********
The script I wrote to create the table is:
CREATE TABLE LOGIN(
USERNAME INTEGER NOT NULL CHECK(USERNAME != NULL),
PASSWORD VARCHAR(10) NOT NULL CHECK(PASSWORD <>'' AND USERNAME != NULL)
);
This is the script I used to modify the column from Integer to Varchar:
ALTER TABLE LOGIN ALTER COLUMN USERNAME TYPE varchar(20);
I appreciate any help. Thanks.
Use USING expression. It allows you to define value conversion:
ALTER TABLE LOGIN ALTER COLUMN USERNAME TYPE varchar(20) USING ...expression...;
From PostgreSQL documentation:
The optional USING clause specifies how to compute the new column
value from the old; if omitted, the default conversion is the same as
an assignment cast from old data type to new. A USING clause must be
provided if there is no implicit or assignment cast from old to new
type.
The cause of the error is the useless additional check constraint (<> null) that you have:
operator does not exist: character varying <> integer :
refers to the condition USERNAME != NULL in both of your check constraints.
(the "not equals" operator in SQL is <> and != gets re-written into that)
So you first need to get rid of those check constraints. The default generated name for that check would be login_username_check, so the following will most probably work:
alter table login
drop constraint login_username_check;
The other check is most probably login_check:
alter table login
drop constraint login_check;
Once those check constraints are dropped you can alter the data type:
ALTER TABLE LOGIN
ALTER COLUMN USERNAME set data TYPE varchar(20);
Now you need to re-add the constraint for the password:
alter table login
add constraint check_password check (password <> '');
If for some reason the generated constraint names are different then the ones I assumes, you can find the names using:
select c.conname, c.consrc
from pg_constraint c
join pg_class t on c.conrelid = t.oid
join pg_namespace n on t.relnamespace = n.oid
where t.relname = 'login'
and n.nspname = 'public'; --<< change here for the correct schema name
As jarlh has already commented, defining a column as NOT NULL is enough. There is no need to add another "not null" check. Plus: the check is wrong anyway. You can't compare a value against null using = or <>. To test for a not null value you need to use IS NOT NULL. The correct way to write an explicit check constraint would be
username check (username is not null)
The problem is in USERNAME's CHECK constraint. You may get a way out of it using catalog pg_constraint somehow like that:
SELECT conname, consrc
FROM pg_constraint
WHERE conrelid =
(SELECT oid
FROM pg_class
WHERE relname LIKE 'login');
In a field 'consrc' you may notice that constraints actually look like "(username <> NULL::integer)", and it brings an error when you try to change column type from integer to varchar.
To remove constraints use
ALTER TABLE LOGIN DROP CONSTRAINT login_username_check;
ALTER TABLE LOGIN DROP CONSTRAINT login_check;
where 'login_username_check' and 'login_check' are connames you got from query above (be careful and doublecheck that names).
After that you should try to
ALTER TABLE LOGIN ALTER COLUMN USERNAME TYPE varchar(20);
This should work if your table has no data in it. If it doesn't, add a
ALTER TABLE dev.tests_LOGIN ALTER COLUMN USERNAME TYPE varchar(20) USING USERNAME::VARCHAR;
Than you probably want to restore PASSWORD<>'' check, so you'll have to do one more alter to bring it back. Good luck!
Some PostgreSQL documentation you may find handy:
pg_constraint doc
alter doc
PS: As mentioned above, you don't need to get a constraint (!=NULL) check when you already have NOT NULL in column description. Also, NULL checks are a bit different. Quick illustration:
SELECT (NULL = NULL);
SELECT (NULL != NULL);
SELECT (NULL IS NULL);
SELECT (NULL IS NOT NULL);

Validating json string using CHECK constraint in Postgres (sql)

I have a table with below schema :
CREATE TABLE tbl_name (
id bigserial primary key,
phone_info json
);
Sample json data for phone_info column is given below .
{
"STATUS":{"1010101010":"1","2020202020":"1"},
"1010101010":"OK",
"2020202020":"OK"
}
Now I need to add a check constraint on phone_info column so that all key for "STATUS" ie(1010101010,2020202020) should exist as a (key,value) pair of phone_info column where value would be "OK".
So above sample data would satisfy the check constraint as there are following key value pair exists in phone_info column.
"1010101010":"OK"
"2020202020,":"OK"
I have tried below solution but this has not worked because array_agg function is not supported with check constraints.
ALTER TABLE tbl_name
ADD CONSTRAINT validate_info CHECK ('OK' = ALL(array_agg(phone_info->json_object_keys(phone_info->'STATUS'))) );
Can someone please help me out , Can I write a SQL function and use the function in check constraint?
With something like this I think you'll want an SQL function.
CREATE TABLE tjson AS SELECT '{
"STATUS":{"1010101010":"1","2020202020":"1"},
"1010101010":"OK",
"2020202020":"OK"
}'::json AS col;
perhaps something like:
CREATE OR REPLACE FUNCTION my_json_valid(json) RETURNS boolean AS $$
SELECT bool_and(coalesce($1->>k = 'OK','f'))
FROM json_object_keys($1->'STATUS') k;
$$ LANGUAGE sql IMMUTABLE;
... but remember that while PostgreSQL will let you modify that function, doing so can cause previously valid rows to become invalid in the table. Never modify this function without dropping the constraint then adding it back again.

Boolean giving invalid datatype - Oracle

I am trying to create a table in Oracle SQL Developer but I am getting error ORA-00902.
Here is my schema for the table creation
CREATE TABLE APPOINTMENT(
Appointment NUMBER(8) NOT NULL,
PatientID NUMBER(8) NOT NULL,
DateOfVisit DATE NOT NULL,
PhysioName VARCHAR2(50) NOT NULL,
MassageOffered BOOLEAN NOT NULL, <-- the line giving the error -->
CONSTRAINT APPOINTMENT_PK PRIMARY KEY (Appointment)
);
What am I doing wrong?
Thanks in advance
Last I heard there were no boolean type in oracle. Use number(1) instead!
Oracle does not support the boolean data type at schema level, though it is supported in PL/SQL blocks. By schema level, I mean you cannot create table columns with type as boolean, nor nested table types of records with one of the columns as boolean. You have that freedom in PL/SQL though, where you can create a record type collection with a boolean column.
As a workaround I would suggest use CHAR(1 byte) type, as it will take just one byte to store your value, as opposed to two bytes for NUMBER format. Read more about data types and sizes here on Oracle Docs.
Oracle doesn't support boolean for table column datatype. You should probably use a CHAR(1) (Y/N)
You can see more info on this other answer
i think u got a below good result
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/datatypes.htm#CJACJGBG
When using an Entity class to create the schema, defining the boolean value as below will help
#Column(columnDefinition = "number default 0")
private boolean picked;