sqlite - how to insert a record using a subselect - sql

I have the following table:
CREATE TABLE group_members(id integer primary key AUTOINCREMENT, group_id integer, member_id integer, FOREIGN KEY (member_id) REFERENCES users(id));
I'm trying to insert a record into the group_members table by selecting the value for group_id from the user table, and then passing in a value for the member_id.
insert into group_members (group_id, member_id)
values (select id from users where code ='12345' and location='multiple', 281);
Where 281 is the member id I'm trying to pass in.
But I'm getting the following error message:
Error: near "select": syntax error
Can you point me in the right direction?

Subqueries must be written in parentheses. The parentheses in your queries already belong to the VALUES clause, so you need another pair:
INSERT INTO group_members (group_id, member_id)
VALUES ((SELECT id FROM users WHERE code ='12345' AND location='multiple'), 281);
Alternatively, use the other form of the INSERT statement that uses a query instead of the VALUES clause:
INSERT INTO group_members (group_id, member_id)
SELECT id, 281 FROM users WHERE code ='12345' AND location='multiple';

Related

INSERT + SELECT data type mismatch on similar fields

I'm running the following SQLite workaround to add a primary key to a table that did not have one. I am getting a datatype mismatch on
INSERT INTO cities
SELECT id, name FROM old_cities;
However, the fields have exactly the same type. Is it possible that his happens due to running the queries from DbBrowser for SQLite?
CREATE table cities (
id INTEGER NOT NULL,
name TEXT NOT NULL
);
INSERT INTO cities (id, name)
VALUES ('pan', 'doul');
END TRANSACTION;
PRAGMA foreign_keys=off;
BEGIN TRANSACTION;
ALTER TABLE cities RENAME TO old_cities;
--CREATE TABLE cities (
-- id INTEGER NOT NULL PRIMARY KEY,
-- name TEXT NOT NULL
--);
CREATE TABLE cities (
id INTEGER NOT NULL,
name TEXT NOT NULL,
PRIMARY KEY (id)
);
SELECT * FROM old_cities;
INSERT INTO cities
SELECT id, name FROM old_cities;
DROP TABLE old_cities;
COMMIT;
You have defined the column id of the table cities to be INTEGER, but with this:
INSERT INTO cities (id, name) VALUES ('pan', 'doul');
you insert the string 'pan' as id.
SQLite does not do any type checking in this case and allows it.
Did you mean to insert 2 rows each having the names 'pan' and 'doul'?
If so, you should do something like:
INSERT INTO cities (id, name) VALUES (1, 'pan'), (2, 'doul');
Later you rename the table cities to old_cities and you recreate cities but you do something different: you define id as INTEGER and PRIMARY KEY.
This definition is the only one that forces type checking in SQLite.
So, when you try to insert the rows from old_cities to cities you get an error because 'pan' is not allowed in the column id as it is defined now.

Generate uuid and then insert data from another table

I have 2 tables in Postgres
main
entity
id
id
name
name
main_id
I need to generate id for entity, get name and id from main and insert into entity table
INSERT INTO entity (select uuid_generate_v4(), name, main_id)
SELECT name, id FROM main
But I get this error
ERROR: syntax error at or near "SELECT"
I know that the point is that I am inserting more arguments than I receive, but I do not know how to proceed further
The first pair of parentheses define the target columns of the INSERT statement. You need to move the UUID generation to the SELECT part:
INSERT INTO entity (id, name, main_id)
SELECT uuid_generate_v4(), name, id
FROM main

PostgreSQL randomize foreign key

I have 2 tables in Postgres ( inventory table and event table ).
In the inventory table my primary key consist of 8 strings.
Example '03163161'.
Now I have to input them in the Event table randomly with the primary key that is on the inventory table.
In what way can I do it? I've tried googling it but no one seems to have a solution on it and I'm trying to experiment on how i can random input the PK of inventory table to the event table since the data is almost 3k.
Update#1
I've tried using the code below
INSERT INTO dashboard.event(terminal_id) VALUES (SELECT terminal_id FROM dashboard.inventory)
but i get the error:
ERROR: syntax error at or near "SELECT"
LINE 1: INSERT INTO dashboard.event(terminal_id) VALUES (SELECT term...
^
SQL state: 42601
Character: 50
Don't use the keyword VALUES with a select in the insert. See this question:
Update or Insert (multiple rows and columns) from subquery in PostgreSQL
INSERT INTO dashboard.event(terminal_id)
SELECT terminal_id
FROM dashboard.inventory --should work
I think you want the 'references' keyword. For example:
https://www.postgresql.org/docs/current/ddl-constraints.html
create table inventory
(
id INTEGER NOT NULL UNIQUE,
... other fields
);
create table events
(
eid INTEGER REFERENCES inventory(id),
... other fields
);

How can I insert a row that references another postgres table via foreign key, and creates the foreign row too if it doesn't exist?

In Postgres, is there a way to atomically insert a row into a table, where one column references another table, and we look up to see if the desired row exists in the referenced table and inserts it as well if it is not?
For example, say we have a US states table and a cities table which references the states table:
CREATE TABLE states (
state_id serial primary key,
name text
);
CREATE TABLE cities (
city_id serial,
name text,
state_id int references states(state_id)
);
When I want to add the city of Austin, Texas, I want to be able to see whether Texas exists in the states table, and if so use its state_id in the new row I'm inserting in the cities table. If Texas doesn't exist in the states table, I want to create it and then use its id in the cities table.
I tried this query, but I got an error saying
ERROR: WITH clause containing a data-modifying statement must be at the top level
LINE 2: WITH inserted AS (
^
WITH state_id AS (
WITH inserted AS (
INSERT INTO states(name)
VALUES ('Texas')
ON CONFLICT DO NOTHING
RETURNING state_id),
already_there AS (
SELECT state_id FROM states
WHERE name='Texas')
SELECT * FROM inserted
UNION
SELECT * FROM already_there)
INSERT INTO cities(name, state_id)
VALUES
('Austin', (SELECT state_id FROM state_id));
Am I overlooking a simple solution?
Here is one option:
with inserted as (
insert into states(name) values ('Texas')
on conflict do nothing
returning state_id
)
insert into cities(name, state_id)
values (
'Dallas',
coalesce(
(select state_id from inserted),
(select state_id from states where name = 'Texas')
)
);
The idea is to attempt to insert in a CTE, and then, in the main insert, check if a value was inserted, else select it.
For this to work properly, you need a unique constraint on states(name):
create table states (
state_id serial primary key,
name text unique
);
Demo on DB Fiddlde
You can force the insert statement to return a value:
WITH inserted AS (
INSERT INTO states (name)
VALUES ('Texas')
ON CONFLICT (name) DO UPDATE SET name = EXCLUDED.NAME
RETURNING state_id
)
. . .
The DO UPDATE SET forces the INSERT to return something.
I notice that you don't have a unique constraint, so you also need that:
ALTER TABLE states ADD CONSTRAINT unq_state_name
UNIQUE (name);
Otherwise the ON CONFLICT doesn't have anything to work with.

H2 INSERT SELECT ON DUPLICATE KEY UPDATE throws "Unique index or primary key violation" error

H2 (started with MODE=MYSQL on) supports INSERT ON DUPLICATE KEY UPDATE statement only with VALUES clause, while throws a "Unique index or primary key violation" error when using INSERT SELECT statement.
Here is an example:
-- creating a simple table
CREATE TABLE test_table1 (
id INT NOT NULL,
value VARCHAR(255) NOT NULL,
PRIMARY KEY (id))
ENGINE = InnoDB;
-- inserting a value
INSERT INTO test_table1
VALUES (1, 'test1');
-- trying to insert on duplicate key update: it works!
INSERT INTO test_table1
VALUES (1, 'test2')
ON DUPLICATE KEY UPDATE value='test2';
-- trying using INSERT SELECT: it throws Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.TEST_TABLE1(ID)"
INSERT INTO test_table1
SELECT 1, 'test2'
FROM test_table1
ON DUPLICATE KEY UPDATE value='test2';
I'm using H2 db version 1.4.192.
Is it a bug? Or is there something wrong with my code?
Thank you
On you H2 console, if you have 'HIBERNATE_SEQUENCES' table make sure to check what is the NEXT_VAL for SEQUENCE_NAME = 'default'.
In my case, I had 2 row (insert statement) in my /src/main/resources/data.sql and the NEXT_VAL was 2 which was causing problems. I changed to 3 with update statement, and it now works fine.
Is there something wrong with my code?
Yes, there is. Why are you inserting into an auto-increment column? You should be specifying the columns with non-autogenerated data. So:
INSERT INTO test_table1(value)
VALUES ('test1');
And:
INSERT INTO test_table1(value)
SELECT 'test2'
FROM test_table1
ON DUPLICATE KEY UPDATE value = VALUES(value);
Your are getting the error because ON DUPLICATE KEY resets value, but that has nothing to do with the primary key on the table.