lo_create(0) how to use with insert query - sql

insert into hospital_image
select 'HospitalImage',
lo_from_bytea(1,decode('/9j/4AAQSkZJRgABAQEA3ADcAAD','base64')),
'jpg',
'123'
where not exists (select null from pg_largeObject where loid=1);
CREATE TABLE hospital_image (
key character varying(30) NOT NULL,
image oid NOT NULL,
mime_type character varying(30) NOT NULL,
version numeric(8,0) NOT NULL,
CONSTRAINT
pk_hospital_image PRIMARY KEY (key)
) WITH ( OIDS=FALSE );
ALTER TABLE
hospital_image OWNER TO postgres;
Here in the above Statement we are supplying the loid manually as 1. Instead we want to get the loid dynamically using lo_create(0). When I use lo_create(0) as per the Postgres docs, Iget an exception.
I used both lo_creat(-1) and lo_create(0). Both doesn't work. It is saying loid exists already. how to use the above functions in my query.
My SQL statement for including a variable OID is:
INSERT INTO hospital_image (key, image, mime_type, version)
VALUES ('MainLogoImage99999',
lo_from_bytea(lo_create(0),
decode('/9j4AAQSkZJRgABAQEA3ADcAAD',
'base64'))‌​,
'jpg',
123);
The error message is:
ERROR: duplicate key value violates unique constraint "pg_largeobject_metadata_oid_index"
SQL state: 23505
Detail: Key (oid)=(34773) already exists.

Both lo_creat(-1) (the argument doesn't matter) and lo_create(0) will create a new large object and return its OID.
lo_create(-1) is the same as lo_create(4294967295) – OIDs are unsigned 4-byte integers.
lo_from_bytea also creates a new large object, so if you pass it the result from lo_create, it complains that it cannot create a large object with the same number again.
Just pass 0 instead of lo_create(0) as the first argument to lo_from_bytea.

Related

How to insert without giving column names but not giving identity column

Table definition:
CREATE TABLE IF NOT EXISTS public.test
(
"Id" integer NOT NULL GENERATED ALWAYS AS IDENTITY (INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1),
"SomeColumn" character(100) COLLATE pg_catalog."default",
CONSTRAINT test_pkey PRIMARY KEY ("Id")
)
TABLESPACE pg_default;
ALTER TABLE IF EXISTS public.test
OWNER to postgres;
I am trying this query:
INSERT INTO public.test VALUES ('testData');
But PostgreSQL throws this error:
ERROR: invalid input syntax for type integer: "testData"
LINE 1: INSERT INTO public.test VALUES ('testData');
I know this is valid in SQL Server. Is there a way the achieve this behaviour in PostgreSQL?
I do not want to specify the column names. Columns are defined in the order, but the identity column does not exist in the query.
I want to not give the column names
That's a bad idea. You should always specify the target columns for an INSERT statement. Especially if you want to skip some, but not others.
However, if you insist on bad coding style, you can use the DEFAULT keyword
INSERT INTO public.test VALUES (DEFAULT, 'testData');

Why is the column not altering when I try to convert it to UUID?

I have a primary key column in my SQL table in PostgreSQL named "id". It is a "bigseries" column. I want to convert the column to a "UUID" column. It entered the below command in the terminal:
alter table people alter column id uuid;
and
alter table people alter column id uuid using (uuid_generate_v4());
but neither of them worked.
In both tries I got the error message
ERROR: syntax error at or near "uuid"
LINE 1: alter table people alter column id uuid using (uuid_generate...
What is the correct syntax?
First of all uuid_generate_v4() is a function which is provided by an extension called uuid-ossp. You should have install that extension by using;
CREATE EXTENSION uuid-ossp;
Postgresql 13 introduced a new function which does basically the same without installing extension. The function is called gen_random_uuid()
Suppose that we have a table like the one below;
CREATE TABLE people (
id bigserial primary key,
data text
);
The bigserial is not a real type. It's a macro which basically creates bigint column with default value and a sequence. The default value is next value of that sequence.
For your use case, to change data type, you first should drop the old default value. Then, alter the type and finally add new default value expression. Here is the sample:
ALTER TABLE people
ALTER id DROP DEFAULT,
ALTER id TYPE uuid using (gen_random_uuid() /* or uuid_generate_v4() */ ),
ALTER id SET DEFAULT gen_random_uuid() /* or uuid_generate_v4() */ ;
CREATE TABLE IF NOT EXISTS people (
id uuid NOT NULL CONSTRAINT people_pkey PRIMARY KEY,
address varchar,
city varchar(255),
country varchar(255),
email varchar(255),
phone varchar(255)
);
This is the correct syntax to create table in postgres SQL, it's better to do these constraints at beginning to avoid any error.
For using alter command you would do the following:
ALTER TABLE customer ADD COLUMN cid uuid PRIMARY KEY;
Most of errors that you could find while writing command either lower case or undefined correct the table name or column.

Postgres breaking null constraint on a serial column

I have a table that I create independently, the primary key is set with the serial type and a sequence applied to the table, but when I try to insert a value a NULL CONSTRAINT error is thrown and the return looks like null was passed, am I missing something in the INSERT statement?
SQL for table generation:
DROP TABLE IF EXISTS public."Team" CASCADE;
CREATE TABLE public."Team" (
"IdTeam" serial PRIMARY KEY,
name text NOT null,
CONSTRAINT "pKeyTeamUnique" UNIQUE ("IdTeam")
);
ALTER TABLE public."Team" OWNER TO postgres;
DROP SEQUENCE IF EXISTS public."Team_IdTeam_seq" CASCADE;
CREATE SEQUENCE public."Team_IdTeam_seq"
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public."Team_IdTeam_seq" OWNER TO postgres;
ALTER SEQUENCE public."Team_IdTeam_seq" OWNED BY public."Team"."IdTeam";
SQL for insert :
INSERT INTO public."Team" (name) values ('Manchester Untited');
The returning error:
ERROR: null value in column "IdTeam" violates not-null constraint
DETAIL: Failing row contains (null, Manchester Untited).
SQL state: 23502
I am baffled. Why are you trying to define your own sequence when the column is already defined as serial?
Second, a primary key constraint is already unique. There is no need for a separate unique constraint.
Third, quoting identifiers just makes the code harder to write and to read.
You can just do:
DROP TABLE IF EXISTS public.Team CASCADE;
CREATE TABLE public.Team (
IdTeam serial PRIMARY KEY,
name text NOT null
);
INSERT INTO public.Team (name)
VALUES ('Manchester Untited');
Dropping the sequence causes the default definition for the IdTeam column to be dropped. After recreating the sequence you will have to recreate the default definition.

Sequence in Oracle/PostgreSQL with no ID in insert statement

I'm try to create table with clever sequence generator for using this insert-strucure:
insert into SOMEUSERS (SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values ('Artem', 'PracTimPatie');
instead of this:
insert into SOMEUSERS (SOMEUSERS_ID, SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values (2, 'Artem', 'PracTimPatie');
or this structure:
insert into SOMEUSERS (SOMEUSERS_ID, SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values (GEN_ID_SOMEUSERS.nextval, 'Artem', 'PracTimPatie');
When I executing the following sql script:
create sequence gen_id_someUsers START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
CREATE TABLE loc_db.someUsers
( someUsers_id number(10) DEFAULT gen_id_someUsers.NEXTVAL NOT NULL, --because of this row
someUsers_name varchar2(50) NOT NULL,
someUsers_password varchar2(50),
CONSTRAINT someUsers_pk PRIMARY KEY (someUsers_id)
);
the following notice is given to me:
Error report - SQL Error: ORA-00984: column not allowed here
00984. 00000 - "column not allowed here"
For clarity, said that in this case:
...
CREATE TABLE loc_db.someUsers
( someUsers_id number(10) NOT NULL, --correct this row
...
Sequence GEN_ID_SOMEUSERS created.
Table LOC_DB.SOMEUSERS created.
How can I configure comfortable sequence generator?
(in case of PostgreSQL too. If possible with no trigger(as easily as possible)
Oracle 12c introduces Identity columns:
CREATE TABLE SOMEUSERS (
SOMEUSERS_ID NUMBER(10) GENERATED ALWAYS AS IDENTITY
CONSTRAINT SOMEUSERS__SOMEUSERS_ID__PK PRIMARY KEY,
SOMEUSERS_NAME VARCHAR2(50)
CONSTRAINT SOMEUSERS__SOMEUSERS_NAME__NN NOT NULL,
SOMEUSERS_PASSWORD VARCHAR2(50)
);
If you want to do it in earlier versions then you will need a trigger and a sequence:
CREATE TABLE SOMEUSERS (
SOMEUSERS_ID NUMBER(10)
CONSTRAINT SOMEUSERS__SOMEUSERS_ID__PK PRIMARY KEY,
SOMEUSERS_NAME VARCHAR2(50)
CONSTRAINT SOMEUSERS__SOMEUSERS_NAME__NN NOT NULL,
SOMEUSERS_PASSWORD VARCHAR2(50)
);
/
CREATE SEQUENCE gen_id_someUsers START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
/
CREATE OR REPLACE TRIGGER SOMEUSERS__ID__TRG
BEFORE INSERT ON SOMEUSERS
FOR EACH ROW
BEGIN
:new.SOMEUSERS_ID := gen_id_someUsers.NEXTVAL;
END;
/
You can then just do (either with the identity column or the trigger combined with your sequence):
INSERT INTO SOMEUSERS (
SOMEUSERS_NAME,
SOMEUSERS_PASSWORD
) VALUES (
'Name',
'Password'
);
In postgres just use a serial like this:
CREATE TABLE SOMEUSERS (
SOMEUSERS_ID serial NOT NULL,
SOMEUSERS_NAME text,
SOMEUSERS_PASSWORD text
);
Your insert statement is then easy as:
INSERT INTO SOMEUSERS (SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values ('Artem', 'PracTimPatie');
If you wanna query the sequence you can just query it like any other relation.
Other answers have addressed postgreSQL and Oracle 12c, so I'll address Oracle 11.2 or earlier here.
From the 11.1 SQL Reference Manual:
DEFAULT
The DEFAULT clause lets you specify a value to be assigned to the column if a subsequent INSERT statement omits a value for the column. The datatype of the expression must match the datatype of the column. The column must also be long enough to hold this expression.
The DEFAULT expression can include any SQL function as long as the function does not return a literal argument, a column reference, or a nested function invocation.
Restriction on Default Column Values
A DEFAULT expression cannot contain references to PL/SQL functions or to other columns, the pseudocolumns CURRVAL, NEXTVAL, LEVEL, PRIOR, and ROWNUM, or date constants that are not fully specified.
(Emphasis mine)
So since you can't put sequence.NEXTVAL in as a DEFAULT value you're basically going to have to use a trigger:
CREATE OR REPLACE TRIGGER SOMEUSERS_BI
BEFORE INSERT
ON LOC_DB.SOMEUSERS
FOR EACH ROW
BEGIN
IF :NEW.SOMEUSERS_ID THEN
:NEW.SOMEUSERS_ID := GEN_ID_SOMEUSERS.NEXTVAL;
END IF;
END SOMEUSERS_BI;
In my experience there is no reliable alternative to using a trigger such as this in Oracle 11.2 or earlier.
Best of luck.

PostgreSQL - Error: SQL state: XX000

I have a table in Postgres that looks like this:
CREATE TABLE "Population"
(
"Id" bigint NOT NULL DEFAULT nextval('"population_Id_seq"'::regclass),
"Name" character varying(255) NOT NULL,
"Description" character varying(1024),
"IsVisible" boolean NOT NULL
CONSTRAINT "pk_Population" PRIMARY KEY ("Id")
)
WITH (
OIDS=FALSE
);
And a select function that looks like this:
CREATE OR REPLACE FUNCTION "Population_SelectAll"()
RETURNS SETOF "Population" AS
$BODY$select
"Id",
"Name",
"Description",
"IsVisible"
from "Population";
$BODY$
LANGUAGE 'sql' STABLE
COST 100
Calling the select function returns all the rows in the table as expected.
I have a need to add a couple of columns to the table (both of which are foreign keys to other tables in the database). This gives me a new table def as follows:
CREATE TABLE "Population"
(
"Id" bigint NOT NULL DEFAULT nextval('"population_Id_seq"'::regclass),
"Name" character varying(255) NOT NULL,
"Description" character varying(1024),
"IsVisible" boolean NOT NULL,
"DefaultSpeciesId" bigint NOT NULL,
"DefaultEcotypeId" bigint NOT NULL,
CONSTRAINT "pk_Population" PRIMARY KEY ("Id"),
CONSTRAINT "fk_Population_DefaultEcotypeId" FOREIGN KEY ("DefaultEcotypeId")
REFERENCES "Ecotype" ("Id") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT "fk_Population_DefaultSpeciesId" FOREIGN KEY ("DefaultSpeciesId")
REFERENCES "Species" ("Id") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
and function:
CREATE OR REPLACE FUNCTION "Population_SelectAll"()
RETURNS SETOF "Population" AS
$BODY$select
"Id",
"Name",
"Description",
"IsVisible",
"DefaultSpeciesId",
"DefaultEcotypeId"
from "Population";
$BODY$
LANGUAGE 'sql' STABLE
COST 100
ROWS 1000;
Calling the function after these changes results in the following error message:
ERROR: could not find attribute 11 in subquery targetlist
SQL state: XX000
What is causing this error and how do I fix it? I have tried to drop and recreate the columns and function - but the same error occurs.
Platform is PostgreSQL 8.4 running on Windows Server. Thanks.
Did you dropping and recreating the function?
By the way, you gotta love how user friendly Postgres is. What other database would you hugs and kisses(XXOOO) as an error state?
When I've seen something similar in the past, it was because the database connection cached certain function attributes. So if I was using pgAdmin, I had to close the SQL editor window and establish a new connection in order to get the function to work correctly. If you haven't already, be sure you are testing the function on new db connections.
I thought the issue was fixed a few versions ago in PostgreSQL, but it's worth a try.
Found a bit easier for me solution: created a backup of the database and restored it from this backup.