Two or more table with serial with uniq nums in every table - sql

I've 2 table with serial field (in table "m" it's field "uniq" and in table "u" it's field "uniq").
But, if I insert data in (for example) u. Autoincrement function make +1 for next row in u (from 1 to 2), but if after this action I insert data in another table (for example) m autoincrement field write down not next value in column (1,2,3..), but 3, even if in field was 1.
It means, what autoincrement function incremented every single value in database in series, but not in the table.
sorry for such a poor description of the problem and bad english = )

Try something like this if you want having an id which is unique in all tables:
CREATE SEQUENCE id_seq;
CREATE TABLE table1(id INTEGER PRIMARY KEY DEFAULT NEXTVAL('id_seq'),Test1 varchar);
CREATE TABLE table2(id INTEGER PRIMARY KEY DEFAULT NEXTVAL('id_seq'),Test2 varchar);
try something like this to create unique id for each table
CREATE TABLE table3(id serial,Test3 varchar);
CREATE TABLE table4(id serial,Test4 varchar);
SQL Fiddle

If I understand correctly, you want a unique ID over tables "a" and "b". So create one table with a serial column just for having your key (eg. "id_table") and all other tables have this key as foreign key. Every time you need a new ID, you insert in your "id_table" and point to this new key.

Related

Oracle SQL: "GENERATED ALWAYS" with a specified sequence

I have two tables that I would like to let them share the same sequence to populate the primary key ID column. However, I also don't want the user to specify or change the value for the ID column.
By using the code below, I can let two tables share the same sequence.
CREATE TABLE T1
(
ID INTEGER DEFAULT SEQ_1.nextval NOT NULL
);
This code will use its own sequence and prevent users from changing or specifying with INSERT:
CREATE TABLE T1
(
ID INTEGER GENERATED ALWAYS AS IDENTITY NOT NULL
);
Is there a way that can both world? Something like this:
CREATE TABLE T1
(
ID INTEGER GENERATED ALWAYS AS ( SEQ_1.nextval ) NOT NULL
);
Regarding the use case, as #Sujitmohanty30 asked, the reason that I raised this question:
I'm thinking to implement inheritance in the database, consider this UML diagram (I can't directly post images due to insufficient reputation, and sorry for being lack of imagination).
ANIMAL is abstract and all inheritance is mandatory. This means no instance of ANIMAL should be created. Furthermore, there is an one-to-many relationship between ANIMAL and ZOO_KEEPER.
Therefore, I came up with this idea:
CREATE SEQUENCE ANIMAL_ID_SEQ;
CREATE TABLE HORSE
(
ID INT DEFAULT ANIMAL_ID_SEQ.nextval NOT NULL PRIMARY KEY,
HEIGHT DECIMAL(3, 2) NOT NULL
);
CREATE TABLE DOLPHIN
(
ID INT DEFAULT ANIMAL_ID_SEQ.nextval NOT NULL PRIMARY KEY,
LENGTH DECIMAL(3, 2) NOT NULL
);
CREATE MATERIALIZED VIEW LOG ON HORSE WITH ROWID;
CREATE MATERIALIZED VIEW LOG ON DOLPHIN WITH ROWID;
CREATE MATERIALIZED VIEW ANIMAL
REFRESH FAST ON COMMIT
AS
SELECT 'horse' AS TYPE, ROWID AS RID, ID -- TYPE column is used as a UNION ALL marker
FROM HORSE
UNION ALL
SELECT 'dolphin' AS TYPE, ROWID AS RID, ID
FROM DOLPHIN;
ALTER TABLE ANIMAL
ADD CONSTRAINT ANIMAL_PK PRIMARY KEY (ID);
CREATE TABLE ZOO_KEEPER
(
NAME VARCHAR(50) NOT NULL PRIMARY KEY,
ANIMAL_ID INT NOT NULL REFERENCES ANIMAL (ID)
);
In this case, the use of the shared sequence is to avoid collision in ANIMAL mview. It uses DEFAULT to get the next ID of the shared sequence. However, using DEFAULT doesn't prevent users from manually INSERTing the ID field or UPDATE the value of it.
You can create a master view/table and generate the sequence in it.
Then copy it as column values into both tables while inserting.
Another option could be inserting into both tables at same time.Use SEQ.NEXTVAL to insert into first table to get a new ID, and then SEQ.CURRVAL to copy same id in the table.
No, you cant have anything like this because ID is independently generated for each of the tables and this can be done only using sequence when you are inserting the data in both the tables at the same time.
You should normalize your data schema: add column animal_type into the table and create composite primary key on both columns

How do you ensure values from a logging table match objects in other tables ?

I have three tables. Two basic tables listing objects and a third table logging changes in database. Here is an example.
create table individual (ind_id integer, age integer, name varchar);
create table organisation (org_id integer, city varchar, name varchar);
create TABLE log_table (log_id integer, object_id integer, table_name varchar, information json, log_date date);
I want to ensure that any row in the log_table corresponds to an existing object in either the individual table or the organisation table. This means that the insertion
insert into log_table (object_id,table_name,information,log_date) values (13,'organisation','{"some":"interesting","information":"on the changes"}','2017-11-09');
is valid only if the table organisation contains a record with the ID 13.
How can I do that in PostgreSQL ? If this is not possible, then I suppose I will have to create one column for the individual table and one for the organisation table in the log_table.
You need an entity table:
create table entity (
entity_id serial primary key,
entity_type text check (entity_type in ('individual','organization'))
)
create table individual (
ind_id integer primary key references entity (entity_id),
age integer, name varchar
);
create table organisation (
org_id integer primary key references entity (entity_id),
city varchar, name varchar
);
create TABLE log_table (
log_id integer primary key,
entity_id integer references entity (entity_id),
information json, log_date date
);
You could also use triggers to solve this problem . Seperate triggers can be made on individual and organisation table which could be on before update ,after update , after insert actions .
You could add one column in log table which would correspond to action performed in base table i.e update or insert .
Also you could add unique constraint on table name and object id .
This would eventually lead to logging every possible operation in table without changing in application code .
Hope this helps !
Starting from your current design you can enforce what you want declaratively by adding to each entity table a constant checked or computed/virtual table/type variant/tag column and a FK (foreign key) (id, table) to the log table.
You have two kinds/types of logged entities. Google sql/database subtypes/polymorphism/inheritance. Or (anti-pattern) 2/many/multiple FKs to 2/many/multiple tables.

INSERTING a single field into a table, referenced from another table

I need to insert a field in a that references an id field in another table.
The id field it is to going is next to the field 'test' (column - codedescription, table typecategory) and coming from an id field next to the word 'assessment' (column categorydescription, table typecategory)
INSERT INTO codetype
(typecategoryid)
Where codedescription='test'
SELECT id FROM typecategory WHERE categorydescription='Assessment Types'
There are plenty of examples of inserting entire columns but nobody has written how to insert a single field from another table.
table - codetype
id bigserial primary key
codedescription varchar
typecategoryid bigint foreign key to typecatogory on the ID column
Table - typecategory
ID big serial primary key
categorydescription varchar
If the column already exists and there are are already records in the rest of the columns in the table, then you need an UPDATE statement, not an INSERT.
Looks like this post might help you: Update a column of a table with a column of another table in PostgreSQL
maybe
UPDATE codetype c
SET c.typecategoryid = t.id
FROM typecategory t
WHERE c.codedescription = 'test' and t.categorydescription='Assessment Types'

Access SQL - ALTER COLUMN to AutoNumber?

How can you alter a table in MS Access using SQL to change a data type to AutoNumber?
I have tried to following with no success
ALTER TABLE PERSON ALTER COLUMN PERSON_ID Integer PRIMARY KEY counter
);
ALTER TABLE PERSON ALTER COLUMN PERSON_ID Integer PRIMARY KEY AUTONUMBER
);
ALTER TABLE PERSON ALTER COLUMN PERSON_ID Integer PRIMARY KEY AUTOINCREMENT
);
Each time I get the same issue "Syntax error" and it highlights the last word in the SQL.
For a Data Definition (DDL) query in Access you use COUNTER to define an AutoNumber field. You were trying to use both Integer and counter on the same field, and that won't work.
I just tried this and it worked for me in Access 2010:
ALTER TABLE PERSON ALTER COLUMN PERSON_ID COUNTER PRIMARY KEY
Note that in order for this statement to work
the table must be empty, and
the table must not already have a Primary Key, not even on the [PERSON_ID] field.
If the table already has rows in it then Access will not allow you to convert a Numeric (Long Integer) field to AutoNumber. In that case you need to create a new table with the AutoNumber Primary Key and then insert the rows from the old table into the new table.
For example, for an existing table named [PERSON] with columns
PERSON_ID INTEGER
PERSON_NAME TEXT(50)
you need to create a new table
CREATE TABLE PERSON_NEW (PERSON_ID COUNTER PRIMARY KEY, PERSON_NAME TEXT(50))
and then copy the records over
INSERT INTO PERSON_NEW
SELECT * FROM PERSON

PostgreSQL Primary and Foreign Key

Next question to you guys.
I Have two tables STUFF and THINGS. First one with two column: ID and CHECKED.
ID is primary key for this table. it looks like this:
ID CHECKED
1 Y
2 N
3 Y
.....
Second Table, named THINGS, has also a few column but what is important, in last column there should be ID of last thing i put into STUFF ID column
Now, I put:
INSERT INTO STUFF(CHECKED) VALUES 'Y' RETURNING ID
-it will return ID=4
And here is the problem, after that I want to put something to THINGS table which is created like this:
CREATE TABLE THINGS(XXX Varchar(), YYY varchar(), ID2 SERIAL REFERENCES STUFF(ID))
so when i put anything to THINGS:
INSERT INTO TABLE THINGS(XXX, YYY) VALUES('xxx','yyy')
And I want to have in ID2 this number which was the last ID I put into STUFF, because now there is first free number from there :/
Your column ID2 should be integer, not serial.
A serial column increments automatically with every insert. There is no way to make sure ID2 will always have the same value as the ID of your primary table.
The right way to do this is capture the ID returned by the insert into your primary table and do something like INSERT INTO child_table (f1, f2, id2) values('foo', 'bar', captured_id);