Attach sequence to a column and start with 1000 - sql

Apply this sql script:
create table software (
id bigint not null,
name varchar(255),
description varchar(255),
constraint pk_software primary key (id))
;
create sequence software_seq;
Then this one:
alter sequence software_seq start with 1000;;
insert into software (id, name, description) values ( 1, 'Soft1', 'Description1');
Then when insert new software programatically (from java), got new software with id = 24
Why not with 1001? Since 'alter sequence software_seq start with 1000;'

You have a few things wrong here.
First of all, just creating a sequence with a particular name doesn't attach it to the table and column that you want using it. You need to change software.id to use software_seq for default values:
alter table software alter column id set default nextval('software_seq');
and you'll want to change the sequence's ownership too (unless of course you're using the sequence in other places):
OWNED BY table_name.column_name
OWNED BY NONE
The OWNED BY option causes the sequence to be associated with a specific table column, such that if that column (or its whole table) is dropped, the sequence will be automatically dropped as well. If specified, this association replaces any previously specified association for the sequence. The specified table must have the same owner and be in the same schema as the sequence. Specifying OWNED BY NONE removes any existing association, making the sequence "free-standing".
So you should:
alter sequence software_seq owned by software.id;
Then when inserting, you'd either leave out the id:
insert into software (name, description) values ('...', '...');
or specify DEFAULT:
insert into software (id, name, description) values (default, '...', '...');
Your other problem is that start with doesn't do what you think it does:
start
The optional clause START WITH start changes the recorded start value of the sequence. This has no effect on the current sequence value; it simply sets the value that future ALTER SEQUENCE RESTART commands will use.
If you want the sequence to start at 1000 then you can:
alter sequence software_seq restart with 1000;
Alternatively, you could use setval:
select setval('software_seq', 1000);
Of course, you could also use bigserial:
The data types smallserial, serial and bigserial are not true types, but merely a notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT property supported by some other databases). In the current implementation, specifying:
CREATE TABLE tablename (
colname SERIAL
);
is equivalent to specifying:
CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
So using bigserial as the id column type would set up all the sequence stuff for you. Then you'd set the starting value as before using alter sequence or setval.

Probably I got. If one wants to change the sequence, then he should use this syntax:
ALTER SEQUENCE sequenceName [ RESTART WITH long ] [ INCREMENT BY long ]
i.e. use 'RESTART' but not 'START'
I tested: then it really start with 1000 when inserting new value.

Related

How to add missing values of file on COPY command

I have a table with a column that comes from a file, although I'm certain that for the other column the value is missing on the file.
Here's the table:
create table if not exists user(
id varchar(36) primary key,
relevance varchar(3) not null,
constraint relevance_check check (relevance in ('ONE', 'TWO'))
);
The command I want to populated the table with:
copy user(id') from '/home/users_ids.txt';
The problem is that my column relevance is not null, and I'd like to set default values on the relevance column when copying, but I'm not sure if that's possible.
I cant set a default value on the tables because I need to import data from many files and each one would have a different value on the relevance field.
Can I achieve what I want using the copy command or there's another approach for this?
You can set the column's default value just for a while, e.g.:
alter table "user" alter relevance set default 'ONE';
copy "user"(id) from '/home/users_one.txt';
alter table "user" alter relevance set default 'TWO';
copy "user"(id) from '/home/users_two.txt';
alter table "user" alter relevance drop default;
The solution is simple and efficient when you are sure that the import takes place in only one session at a time but is not safe if you intend to use it simultaneously in more than one session. A safer alternative, in this case, could be to use a temporary table, e.g .:
create temp table ids(id text);
copy ids(id) from '/home/users_one.txt';
insert into "user"
select id, 'ONE'
from ids;

ERROR: relation "schema.TableName_Id_seq" does not exist - when creating table in a new database

I'm having an issue where I used pgAdmin4's GUI to create a SQL table, and I want to use to generated CREATE TABLE script to create this same table in another database.
When I run the CREATE TABLE script generated by pgAdmin4 in my new database, I get the following error:
ERROR: relation "schema.TableName_Id_seq" does not exist
So, it appears that the issue is with my auto-incrementing id column that I created as type SERIAL.
The CREATE TABLE script as provided by pgAdmin4:
-- Table: myschema.TableName
-- DROP TABLE myschema."TableName";
CREATE TABLE myschema."TableName"
(
"Id" integer NOT NULL DEFAULT nextval('myschema."TableName_Id_seq"'::regclass),
/* Other columns here */
CONSTRAINT "TableName_pkey" PRIMARY KEY ("Id")
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
ALTER TABLE myschema."TableName"
OWNER to JoshuaSchlichting;
Why can't the CREATE TABLE script be used in another database? The relation "schema.TableName_Id_seq" didn't exist in the original database prior to be creating that table. What's happening that is different?
The DDL script provided by pgAdmin4 is not complete. When the table was created, there was an implicit creation of a sequence because of the SERIAL type being select for the Id column.
You can find this newly create sequence with pgAdmin4. To do this, go to
-> your server
-> your database
-> your schema
-> Sequences
-> Right click TableName_Id_seq
-> choose "Create script"
This reveals the script used to create this sequence. In this instance, the following was revealed:
-- SEQUENCE: myschema.TableName
-- DROP SEQUENCE myschema."TableName";
CREATE SEQUENCE myschema."TableName"
INCREMENT 1
START 1
MINVALUE 1
MAXVALUE 2147483647
CACHE 1;
The use of the CREATE SEQUENCE script can be avoided by changing the line of code used to create the Id column in the CREATE TABLE script. Example below:
original line:
"Id" integer NOT NULL DEFAULT nextval('myschema."TableName_Id_seq"'::regclass),
changed to: "Id" SERIAL NOT NULL,

HSQLDB - link several sequences for several columns of the table

I would like to link several sequences for generating default values for several columns of a table.
For example:
CREATE SEQUENCE seq1 START WITH 1;
CREATE SEQUENCE seq2 START WITH 1;
CREATE TABLE mytable (rid int GENERATED BY DEFAULT AS SEQUENCE seq1 PRIMARY KEY, p63 int GENERATED BY DEFAULT AS SEQUENCE seq2)
Unfortunately, an error is occured: "identity definition not allowed"
In Postgresql is working.
Any idea ?
Thanks
The first use of the sequence is allowed. You can write a BEFORE INSERT TRIGGER to insert sequence values into the second column.
Having the same issue, I came upon this post. I used another workaround :
CREATE SEQUENCE seq1 START WITH 1;
CREATE SEQUENCE seq2 START WITH 1;
CREATE TABLE mytable (
rid int DEFAULT nextval('seq1') NOT NULL,
p63 int NOT NULL
);
ALTER TABLE mytable ALTER p63 SET DEFAULT NEXTVAL('seq2');
Altering the p63 column after table creation made possible to use the seq2 sequence while it was not accepted when creating the table.

How to add a sequence column to an existing table with records

I had created a new table named USERLOG with two fields from a previous VIEW. The table already consist of about 9000 records. The two fields taken from the VIEW, i.e. weblog_views consist of IP (consists of IP address), and WEB_LINK (consists of URL). This is the code I used,
CREATE TABLE USERLOG
AS
SELECT C_IP, WEB_LINK FROM weblog_views;
I want to add another column to this table called the USER_ID, which would consists of a sequence starting with 1 to 9000 records to create a unique id for each existing rows. I need help with this part. I'm using Oracle SQL Developer: ODMiner version 3.0.04.
I tried using the AUTO-INCREMENT option,
ALTER TABLE USERLOG
ADD USER_ID INT UNSIGNED NOT NULL AUTO_INCREMENT;
But I get an error with this,
Error report:
SQL Error: ORA-01735: invalid ALTER TABLE option
01735. 00000 - "invalid ALTER TABLE option"
So, I would really appreciate any help that I can get!
You would need to add a column
ALTER TABLE userlog
ADD( user_id number );
create a sequence
CREATE SEQUENCE user_id_seq
START WITH 1
INCREMENT BY 1
CACHE 20;
Update the data in the table
UPDATE userlog
SET user_id = user_id_seq.nextval
Assuming that you want user_id to be the primary key, you would then add the primary key constraint
ALTER TABLE userlog
ADD CONSTRAINT pk_user_id PRIMARY KEY( user_id );
If you want to use the sequence to automatically add the user_id when you do an INSERT (the other option would be to specifically reference user_id_seq.nextval in your INSERT statements, you would also need a trigger
CREATE OR REPLACE TRIGGER trg_userlog_user_id
BEFORE INSERT ON userlog
FOR EACH ROW
BEGIN
:new.user_id := user_id_seq.nextval;
END;
In addition to Justin's excellent answer you might want to prevent NULL values for your user_id in the future (as they could still be caused by UPDATE statements). Therefore, execute the following statement at the end:
ALTER TABLE userlog MODIFY(user_id number NOT NULL);
Step 1.
Create sequence to be used by the column
eg:
CREATE SEQUENCE user_id_seq
START WITH 1
INCREMENT BY 1
CACHE 20;
Step 2.
Update new column with sequence
eg:
UPDATE userlog
SET user_id = user_id_seq.nextval;
Step 3. - Set Sequence as the default value for the column, will work only above Oracle 12c
ALTER TABLE USERLOG
MODIFY USER_ID INT DEFAULT user_id_seq.nextval;

how to generate primary key values while inserting data into table through pl/sql stored procedure

I need to insert data into particular table through pl/sql stored procedure. My requirements are:
while inserting it should generate PRIMARY KEY values for a particular column;
it should return that PRIMARY KEY value to an output variable; and
for another column it should validate my string such that it should contain only characters, not integers.
You can generate primary key values as a surrogate key using an Oracle SEQUENCE. You can create a constraint on a column that uses TRANSLATE to check that no numeric digits exist in newly inserted/updated data.
Some example code, suitable for SQL*Plus:
CREATE SEQUENCE mysequence;
/
CREATE TABLE mytable (
pkidcol NUMBER PRIMARY KEY,
stringcol VARCHAR2(100)
);
/
ALTER TABLE mytable ADD (
CONSTRAINT stringnonnumeric
CHECK (stringcol = TRANSLATE(stringcol,'A0123456789','A'))
);
/
DECLARE
mystring mytable.stringcol%TYPE := 'Hello World';
myid mytable.pkidcol%TYPE;
BEGIN
INSERT INTO mytable (pkidcol, stringcol)
VALUES (mysequence.NEXTVAL, mystring)
RETURNING pkidcol INTO myid;
END;
/
In oracle I believe the "identity" column is best achieved with a sequence and an insert trigger that checks if the primary key columns is null and if so gets the next sequence and inserts it.
you can then use the "returning" clause to get the newly created primary key:
insert into <table> (<columns>) values (<values>) returning <prim_key> into <variable>;
the filtering of the string field I would personally handle in code before going to the database (if that is a possibility). Databases are notoriously inefficient at handling string operations.