How to insert a boolean value to a table in PostgreSQL? - sql

I come from MySQL to PostgreSQL then, I created test table with BOOLEAN state column in PostgreSQL as shown below:
CREATE TABLE test (
state BOOLEAN -- Here
);
But, I couldn't insert TRUE with 1 and FALSE with 0 to test table as shown below even though the SQL queries below work in MySQL:
INSERT INTO test VALUES (1);
INSERT INTO test VALUES (0);
Then, I got the error below:
ERROR: column "state" is of type boolean but expression is of type integer
So, how to insert a boolean value to a table?

You can insert TRUE with '1' and FALSE with '0' in PostgreSQL as shown below:
INSERT INTO test VALUES ('1');
INSERT INTO test VALUES ('0');
Then, t which is TRUE and f which is FALSE are inserted to test table as shown below:
postgres=# SELECT * FROM test;
state
-------
t
f
(2 rows)
In addtion, these SQL queries below also work to insert TRUE and FALSE to test table as shown below:
TRUE:
INSERT INTO test VALUES (tRuE);
INSERT INTO test VALUES ('TrUe');
INSERT INTO test VALUES ('T');
INSERT INTO test VALUES ('t');
INSERT INTO test VALUES ('YeS');
INSERT INTO test VALUES ('Y');
INSERT INTO test VALUES ('y');
INSERT INTO test VALUES ('oN');
FALSE:
INSERT INTO test VALUES (fAlSe);
INSERT INTO test VALUES ('FaLsE');
INSERT INTO test VALUES ('F');
INSERT INTO test VALUES ('f');
INSERT INTO test VALUES ('No');
INSERT INTO test VALUES ('N');
INSERT INTO test VALUES ('n');
INSERT INTO test VALUES ('oFf');

The standard way to insert boolean values in PostgreSQL is to use the literal boolean values true or false or any expression that evaluates to a boolean.
For example:
create table test (
state boolean
);
insert into test (state) values (true);
insert into test (state) values (false);
insert into test (state) values (3 * 5 > 10);
select * from test;
Returns:
state
-----
t
f
t
See running example in db<>fiddle.

Related

Sql, validation to check a list allowing a delimiter

I want to create a validation in SQL that will check for a value or combination of values that can be delimited with a semi-colon from a list of 3 possible combinations of 'Apples''Oranges' 'Bananas'.
In the example below the validation should pass for the first options but fail for the last
CREATE TABLE Test1(A varchar (50));
INSERT INTO Test1 VALUES ('Apples;Oranges;Bananas');
INSERT INTO Test1 VALUES ('Apples');
INSERT INTO Test1 VALUES ('Apples;Eggs');

Use a returning value from an INSERT table (A) into another table (B)

I need to use the returning value of the Table A (ID) and insert it in Table B as a parameter:
insert into tableA (ID, Name , Address)
values (GEN_ID(GENERATOR,1),'John','123 street')
returning ID
--Example: ID=159
insert into tableB (ID, TABLE_A_FK )
values (GEN_ID(GENERATOR,1), 159)
Instead of entering the actual value 159, can I create like a variable (e.g. declare ID int;), and just pass the parameter?
The only way to do this in a single statement, is to use EXECUTE BLOCK (basically an anonymous one-off procedure). It uses the same syntax as normal stored procedures in Firebird.
You can do:
execute block
as
declare id integer;
begin
insert into tableA (ID, Name , Address)
values (GEN_ID(GENERATOR,1), 'John', '123 street')
returning ID
into id;
insert into tableB (ID, TABLE_A_FK)
values (GEN_ID(GENERATOR,1), :id);
end
If necessary, execute block statements can be parameterized, so you can use parameters to provide values (instead of hard coding them). See the link above for details.

How can i use default value on postgres when query include null value

I use Postgres and I've integration app which write data to database. My column should not be null but my app send null value. I tried to set default value but query override this rule with null value. How can i handle this change without code.
My Column configuration looks like this.
If you won't or can't change the query in code, you have to use trigger
If you can change code structure and query:
If the column has a default value, then no need to send NULL value to query
-- Before change
insert into your_table (id, name, default_col) values
(1, 'name', null);
-- After change (remove null data)
insert into your_table (id, name) values
(1, 'name');
Or send default value in insert query
-- Before change
insert into your_table (id, name, default_col) values
(1, 'name', null);
-- After change (Use default keyboard)
insert into your_table (id, name, default_col) values
(1, 'name', default);

How to write a WHERE clause for NULL value in ARRAY type column?

I created a table which contains a column of string ARRAY type as:
CREATE TABLE test
(
id integer NOT NULL,
list text[] COLLATE pg_catalog."default",
CONSTRAINT test_pkey PRIMARY KEY (id)
)
I then added rows which contain various values for that array, including an empty array and missing data (null):
insert into test (id, list) values (1, array['one', 'two', 'three']);
insert into test (id, list) values (2, array['four']);
insert into test (id, list) values (3, array['']);
insert into test (id, list) values (4, array[]::text[]); // empty array
insert into test (id, list) values (5, null); // missing value
pgAdmin shows table like this:
I am trying to get a row which contains a null value ([null]) in the list column but:
select * from test where list = null;
...returns no rows and:
select * from test where list = '{}';
...returns row with id = 4.
How to write WHERE clause which would target NULL value for column of ARRAY type?
demo:db<>fiddle
... WHERE list IS NULL
select * from test where list IS null;
Like this:
select * from test where list IS NULL;

How to to get the value of an auto increment column in postgres from a .sql script file?

In postgres I have two tables like so
CREATE TABLE foo (
pkey SERIAL PRIMARY KEY,
name TEXT
);
CREATE TABLE bar (
pkey SERIAL PRIMARY KEY,
foo_fk INTEGER REFERENCES foo(pkey) NOT NULL,
other TEXT
);
What I want to do is to write a .sql script file that does the following
INSERT INTO foo(name) VALUES ('A') RETURNING pkey AS abc;
INSERT INTO bar(foo_fk,other) VALUES
(abc, 'other1'),
(abc, 'other2'),
(abc, 'other3');
which produces the error below in pgAdmin
Query result with 1 row discarded.
ERROR: column "abc" does not exist
LINE 3: (abc, 'other1'),
********** Error **********
ERROR: column "abc" does not exist
SQL state: 42703
Character: 122
Outside of a stored procedure how do a define a variable that I can use between statements? Is there some other syntax for being able to insert into bar with the pkey returned from the insert to foo.
You can combine the queries into one. Something like:
with foo_ins as (INSERT INTO foo(name)
VALUES ('A')
RETURNING pkey AS foo_id)
INSERT INTO bar(foo_fk,other)
SELECT foo_id, 'other1' FROM foo_ins
UNION ALL
SELECT foo_id, 'other2' FROM foo_ins
UNION ALL
SELECT foo_id, 'other3' FROM foo_ins;
Other option - use an anonymous PL/pgSQL block like:
DO $$
DECLARE foo_id INTEGER;
BEGIN
INSERT INTO foo(name)
VALUES ('A')
RETURNING pkey INTO foo_id;
INSERT INTO bar(foo_fk,other)
VALUES (foo_id, 'other1'),
(foo_id, 'other2'),
(foo_id, 'other3');
END$$;
You can use lastval() to ...
Return the value most recently returned by nextval in the current session.
This way you do not need to know the name of the seqence used.
INSERT INTO foo(name) VALUES ('A');
INSERT INTO bar(foo_fk,other) VALUES
(lastval(), 'other1')
, (lastval(), 'other2')
, (lastval(), 'other3')
;
This is safe because you control what you called last in your own session.
If you use a writable CTE as proposed by #Ihor, you can still use a short VALUES expression in the 2nd INSERT. Combine it with a CROSS JOIN (or append the CTE name after a comma (, ins) - same thing):
WITH ins AS (
INSERT INTO foo(name)
VALUES ('A')
RETURNING pkey
)
INSERT INTO bar(foo_fk, other)
SELECT ins.pkey, o.other
FROM (
VALUES
('other1'::text)
, ('other2')
, ('other3')
) o(other)
CROSS JOIN ins;
Another option is to use currval
INSERT INTO foo
(name)
VALUES
('A') ;
INSERT INTO bar
(foo_fk,other)
VALUES
(currval('foo_pkey_seq'), 'other1'),
(currval('foo_pkey_seq'), 'other2'),
(currval('foo_pkey_seq'), 'other3');
The automatically created sequence for serial columns is always named <table>_<column>_seq
Edit:
A more "robust" alternative is to use pg_get_serial_sequence as Igor pointed out.
INSERT INTO bar
(foo_fk,other)
VALUES
(currval(pg_get_serial_sequence('public.foo', 'pkey')), 'other1'),
(currval(pg_get_serial_sequence('public.foo', 'pkey')), 'other2'),
(currval(pg_get_serial_sequence('public.foo', 'pkey')), 'other3');