Return ID in MyBatis and PostgreSQL - postgresql

My table plugins has just two columns: ID and DTYPE. I would like to store a String in DTYPE column. ID should increment automatically and be returned by insert method. For that purpose I created manually "id_sequence" like this:
CREATE SEQUENCE id_sequence
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
OWNED BY plugin.id;
This is my mapper.xml file:
<insert id="insert" useGeneratedKeys="true" parameterType="String">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
SELECT CAST(nextval('id_sequence') as INTEGER)
</selectKey>
INSERT INTO plugins (ID, DTYPE)
VALUES ( #{id}, #{plugin})
RETURNING ID;
</insert>
and corresponding mapper.java:
int insert(String plugin);
Problem statement: 1) I cannot get a proper value of ID (it is null), 2) I get an error
SQL: INSERT INTO public.ucpoplugin (ID, DTYPE) VALUES ( ?, CORRECT_STRING)
Cause: org.postgresql.util.PSQLException: FEHLER: Column »id« is of type bigint, but the sentence is has Type character varying.

I recomend to use auto increment on that id column and then do not pass just string as parameter, but pass whole object. After insert that property will be filled.
See: http://edwin.baculsoft.com/2010/12/beginning-mybatis-3-part-3-how-to-get-tables-generated-ids/
Or: Returning values from MyBatis <insert> mapped methods

Related

Output Inserted.id equivalent in Postgres

I am new to PostgreSQL and trying to convert mssql scripts to Postgres.
For Merge statement, we can use insert on conflict update or do nothing but am using the below statement, not sure whether it is the correct way.
MSSQL code:
Declare #tab2(New_Id int not null, Old_Id int not null)
MERGE Tab1 as Target
USING (select * from Tab1
WHERE ColumnId = #ID) as Source on 0 = 1
when not matched by Target then
INSERT
(ColumnId
,Col1
,Col2
,Col3
)
VALUES (Source.ColumnId
,Source.Col1
,Source.Col2
,Source.Col3
)
OUTPUT INSERTED.Id, Source.Id into #tab2(New_Id, Old_Id);
Postgres Code:
Create temp table tab2(New_Id int not null, Old_Id int not null)
With source as( select * from Tab1
WHERE ColumnId = ID)
Insert into Tab1(ColumnId
,Col1
,Col2
,Col3
)
select Source.ColumnId
,Source.Col1
,Source.Col2
,Source.Col3
from source
My query is how to convert OUTPUT INSERTED.Id in postgres.I need this id to insert records in another table (lets say as child tables based on Inserted values in Tab1)
In PostgreSQL's INSERT statements you can choose what the query should return. From the docs on INSERT:
The optional RETURNING clause causes INSERT to compute and return value(s) based on each row actually inserted (or updated, if an ON CONFLICT DO UPDATE clause was used). This is primarily useful for obtaining values that were supplied by defaults, such as a serial sequence number. However, any expression using the table's columns is allowed. The syntax of the RETURNING list is identical to that of the output list of SELECT. Only rows that were successfully inserted or updated will be returned.
Example (shortened form of your query):
WITH [...] INSERT INTO Tab1 ([...]) SELECT [...] FROM [...] RETURNING Tab1.id

How to insert and then update returned Id from insert query as returning id in a single command in postgres?

I have a demo table
CREATE TABLE items (
id SERIAL primary key,
user_id integer,
name character varying,
created timestamp with time zone default now()
);
And I want a single query to run and first insert data, then return primary key using returning id and then update the same table with the returned id.
INSERT INTO items (name) values ('pen') RETURNING id as idd
update items set user_id=(select idd) where id=(select idd)
but the above command doesn't work and throws syntax error.
Any help will be appriciated.
You can do that right within the INSERT statement:
INSERT INTO items
(name, user_id)
values
('pen', currval(pg_get_serial_sequence('items','id')));
Online example
You can try this way also :
create temp table insert_item as
with insert_item_cte as (
INSERT INTO items (name)
values ('pen') returning id
)
select id from insert_item_cte;
update items set user_id = items.id
from insert_item ii
where ii.id = items.id;
Online Demo

How can i create auto increment column to my existing column?

I am working with Oracle 12c in which I have below table structure:-
CREATE TABLE patients (
patient_id Integer NOT NULL,
customer_id Integer NOT NULL,
title varchar(5) NOT NULL,
fname varchar(125) NOT NULL,
lname varchar(125) NOT NULL,
dob date NOT NULL,
is_medical_card NUMBER(1) NOT NULL CHECK (is_medical_card IN (0,1)),
scheme_number Integer NOT NULL,
status varchar(50) NOT NULL,
created_on date NOT NULL,
last_update_date date NOT NULL,
consent_flag NUMBER(1) NOT NULL CHECK (consent_flag IN (0,1)),
relationship varchar(50) NOT NULL
);
Where patient_id is my primary key so now I want to make it auto increment as well so please let me how can I do this so make it auto increment.
Thanks!
Need to create auto increment to existing column.
You might want to use Identities - Creating a table with an Identity gives you the chance to omit the ID values and let Oracle use a sequence on your desired column:
1. Let's Create the Table:
CREATE TABLE identities (
id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
description varchar2(100) NOT NULL
);
Table created.
2. You'll want to create a primary key to ensure uniqueness:
alter table identities add constraint id_pk primary key (ID);
Table altered.
3. Let's insert some data in different ways:
INSERT INTO identities (description)
VALUES('Insert Description omitting ID');
1 row created.
INSERT INTO identities (id,description)
VALUES(NULL,'Insert with explicit NULL value');
1 row created.
4. Save the work done
commit;
Commit complete.
5. Check the results
select * from identities;
ID DESCRIPTION
---------- ---------------------------------------------
1 Insert Description omitting ID
2 Insert with explicit NULL value
As you can see we dind't specify any number for the ID, but the Identity on the ID column did for us
Note: Mind that you can manually insert an ID, but this will mess up with the Identity as it'll normally do with a standard Sequence:
INSERT INTO identities (id,description)
VALUES(3,'Manually insert an ID value');
1 row created.
INSERT INTO identities (description)
VALUES('Test Nextval');
INSERT INTO identities (description)
*
ERROR at line 1:
ORA-00001: unique constraint (XXX.ID_PK) violated
This error, because it tries to insert a '3' into the ID that was manually inserted with the statement before.
Check the table:
select * from identities;
ID DESCRIPTION
---------- ---------------------------------------------
1 Insert Description omitting ID
2 Insert with explicit NULL value
3 Manually insert an ID value
Re-Run the "NEXTVAL" insert:
INSERT INTO identities (description)
VALUES('Test Nextval');
1 row created.
Re-Check the table:
select * from identities;
ID DESCRIPTION
---------- ---------------------------------------------
1 Insert Description omitting ID
2 Insert with explicit NULL value
3 Manually insert an ID value
4 Test Nextval
Hope this Helps.

Default ID with Korma and Postgresql?

I have the following schema:
CREATE TABLE IF NOT EXISTS art_pieces
(
-- Art Data
ID SERIAL PRIMARY KEY,
title TEXT NOT NULL,
description TEXT,
price INT NULL,
-- Relations
artists_id INT NULL
);
--;;
CREATE TABLE IF NOT EXISTS artists
(
-- Art Data
ID SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
This is the corresponding art-piece entity:
(defentity art-pieces
(table :art_pieces)
(entity-fields
:id
:title
:description
:price
:artists_id)
(belongs-to artists))
I'm wondering why the following returns PSQLException ERROR: null value in column "id" violates not-null constraint:
(create-piece {:title "The Silence of the Lambda"
:description "Something something java beans and a nice chianti"
:price 5000})
Shouldn't the ID SERIAL PRIMARY KEY field populate automatically? Is this something to do with Korma's interaction with PSQL?
INSERT INTO "art_pieces" ("description", "id", "price", "title") VALUES (?, NULL, ?, ?)
The problem here is that you try to insert NULL value into id column. Default value is inserted only if you omit the column or use DEFAULT keyword (instead of NULL).
To insert the next value of the sequence into the serial column, specify that the serial column should be assigned its default value. This can be done either by excluding the column from the list of columns in the INSERT statement, or through the use of the DEFAULT key word
PostgreSQL Serial Types
So you have to change the query to:
INSERT INTO "art_pieces" ("description", "id", "price", "title") VALUES (?, DEFAULT, ?, ?)
-- or
INSERT INTO "art_pieces" ("description", "price", "title") VALUES (?, ?, ?)
Another workaround (in case you don't have permissions to change the query) would be to add a trigger function that will replace NULL value in id column automatically:
CREATE OR REPLACE FUNCTION tf_art_pieces_bi() RETURNS trigger AS
$BODY$
BEGIN
-- if insert NULL value into "id" column
IF TG_OP = 'INSERT' AND new.id IS NULL THEN
-- set "id" to the next sequence value
new.id = nextval('art_pieces_id_seq');
END IF;
RETURN new;
END;
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER art_pieces_bi
BEFORE INSERT
ON art_pieces
FOR EACH ROW EXECUTE PROCEDURE tf_art_pieces_bi();

Oracle Default value on Number column

I have a number column on a table called SampleTable which is defined as follows
ID Number(10) DEFAULT 1
I have a trigger on different table(SomeTable) and UPDATE EACH ROW (Trigger - :New.ID) which inserts value from that table(SomeTable) into the SampleTable.
Sometimes the ID from SomeTable can be NULL and I wanted to SampleTable to insert the default value 1 in my case.
But it inserts NULL(Blankspace) on the table.
I am kinda new to PL/SQL so any help is greatly appreciated.
A column default is only used if the column is not specified in the insert:
insert into sampletable (othercol) values ('x'); -- ID will default to 1 here
It is not used if the column has been specified, even if a NULL has been passed in:
insert into sampletable (othercol, id)
values ('x', null); -- ID will be set to null here
To deal with this, your trigger can do this:
insert into sampletable (othercol, id)
values ('x', coalesce(:new.id,1));