Suppose the following setup:
create table chat_message (
id serial primary key,
message_id bigint unique not null, -- id from third party service
message_type varchar(255) unique not null
);
I can upsert into this table like this:
-- insert first record
insert into chat_message
values(1, 1234, 'start_message');
-- upsert
insert into chat_message (message_id, message_type)
values(1260, 'start_message')
on conflict (message_type)
do update set message_id = 1260;
This works fine, but I need to structure the table like this:
create table chat_message (
id serial primary key,
message_id bigint unique not null,
message_type varchar(255) not null -- this isn't necessarily unique
);
How can I accomplish this? Sure, message_id will always be unique, but there could be many messages with message_type = 'start_message'
Related
I have two table: User and Team.
They are in a many-to-many relation.
I would like to get all teams of a specific user.
Seams really simple but I can't find the answer anywhere..
Do you know how can I do ?
On the many-to-many relation must be 3rd table. This table contained user_id and team_id connections.
For example:
CREATE TABLE user (
id serial4 NOT NULL,
first_name varchar(200) NOT NULL,
last_name varchar(200) NULL,
CONSTRAINT user_pk PRIMARY KEY (id)
);
CREATE TABLE team (
id serial4 NOT NULL,
team_name varchar NOT NULL,
team_about text NULL,
CONSTRAINT team_pk PRIMARY KEY (id)
);
CREATE TABLE user_team (
id serial4 NOT NULL,
user_id int4 NOT NULL,
team_id int4 NOT NULL,
CONSTRAINT user_team_pk PRIMARY KEY (id)
);
-- filter and select team by user_id
select t.* from examples.team t
inner join examples.user_team usrt on usrt.team_id = t.id
where usrt.user_id = 2;
I have 2 tables:
CREATE TABLE public."user"
(
id integer NOT NULL DEFAULT nextval('user_id_seq'::regclass),
username character varying(256) COLLATE pg_catalog."default",
CONSTRAINT user_pkey PRIMARY KEY (id)
)
CREATE TABLE public.user_tenant
(
user_id integer NOT NULL,
tenant_id integer NOT NULL,
CONSTRAINT user_fk FOREIGN KEY (user_id)
REFERENCES public."user" (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE
)
I need to have unique values (user.username, user_tenant.tenant_id). How can I declare such a constraint?
I would make the username unique, just like the tenant that is in another table. When that is done, you can put a primary key on the user_id and tenant_id:
CREATE TABLE public."user"
(
id integer NOT NULL DEFAULT nextval('user_id_seq'::regclass),
username character varying(256) COLLATE pg_catalog."default" unique,
CONSTRAINT user_pkey PRIMARY KEY (id)
);
CREATE TABLE public.user_tenant
(
user_id integer NOT NULL,
tenant_id integer NOT NULL,
CONSTRAINT user_fk FOREIGN KEY (user_id)
REFERENCES public."user" (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE,
CONSTRAINT user_tenant_pk PRIMARY KEY (user_id, tenant_id)
);
By the way, don't use reserved names like "user" for table names.
You can create a function which can check for uniqueness across multiple tables (example here: Postgres unique combination constraint across tables) but it looks like you may need to the structure of your tables or follow Frank Heikens' answer.
EDIT:
CREATE TABLE public."user"
(
id SERIAL,
username character varying(256) COLLATE pg_catalog."default",
PRIMARY KEY (id)
);
CREATE TABLE public.user_tenant
(
user_id integer NOT NULL,
tenant_id integer NOT NULL,
CONSTRAINT user_fk FOREIGN KEY (user_id)
REFERENCES public."user" (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE
);
CREATE OR REPLACE FUNCTION public.check_user_tenant(user_id integer, tenant_id integer)
RETURNS boolean AS
$$
DECLARE b_result boolean;
BEGIN
SELECT (COUNT(*) = 0) INTO b_result
FROM public.user u
JOIN public.user_tenant ut ON ut.user_id IN (SELECT id
FROM public.user i_u
WHERE i_u.username = u.username)
WHERE u.id = $1 AND ut.tenant_id = $2;
RETURN b_result;
END
$$ LANGUAGE 'plpgsql';
ALTER TABLE public.user_tenant
ADD CONSTRAINT check_filename CHECK
(public.check_user_tenant(user_id, tenant_id));
-- Testing:
insert into public."user" (username) VALUES ('foo');
insert into public.user_tenant (user_id, tenant_id) VALUES (1,3);
insert into public."user" (username) VALUES ('foo');
-- Violates constraint:
insert into public.user_tenant (user_id, tenant_id) VALUES (2,3);
I want to understand inheritance in postgresql, simple whitch columns in whitch tables.
CREATE TABLE users (
id serial PRIMARY KEY,
username VARCHAR UNIQUE NOT NULL,
email VARCHAR NOT NULL,
password_salt VARCHAR,
password_hash VARCHAR,
avatar serial
)
CREATE TABLE groups (
id serial PRIMARY KEY NOT NULL,
name VARCHAR,
email VARCHAR,
avatar serial,
)
CREATE TABLE accounts (
id serial PRIMARY KEY NOT NULL,
name VARCHAR,
avatar serial,
rating json NOT NULL,
);
CREATE TABLE users_to_accounts (
id serial PRIMARY KEY NOT NULL,
start_time DATETIME NOT NULL,
end_time DATETIME,
)
CREATE TABLE account_subscryptions (
user_id serial NOT NULL,
account_id serial NOT NULL,
) INHERITS users_to_accounts
CREATE TABLE account_memberships (
user_id serial NOT NULL,
account_id serial NOT NULL,
) INHERITS users_to_accounts
CREATE TABLE users_to_groups (
id serial PRIMARY KEY NOT NULL,
start_time DATETIME NOT NULL,
end_time DATETIME,
)
CREATE TABLE group_subscryptions (
user_id serial NOT NULL,
group_id serial NOT NULL,
) INHERITS users_to_groups
CREATE TABLE group_memberships (
user_id serial NOT NULL,
group_id serial NOT NULL,
) INHERITS users_to_groups
Now.
1. Is it good design to have foreign keys in child tables an all common data in "abstract" table?
2. Is there any traps in future changes of database with inherited relantion tables?
3. I am all wrong and there is a better way for this schema?
4. I want to create good database schema and generate graphql api in postgraphile, looking in google for half day, did not gave me any one good or best solution, so every link will by great.
It may be usefull for others, I think. Thanks
cannot add foreign key constraint to table
create table users
(
user_id int auto_increment primary key not null,
username varchar(50) unique null ,
email varchar(50) unique ,
passwords varchar(50) not null,
login_status boolean not null
);
create table category (
category_id int primary key not null,
category_name varchar(50) not null
);
create table answers (
id_answer int auto_increment primary key not null,
answer boolean not null
);
create table questions (
question_id int primary key not null,
category_name varchar(50) not null,
content varchar(50) not null ,
foreign key (category_name) references category (category_name)
);
You get this error because there's no index on category_name in the category table. Change that CREATE statement as follows:
create table category (
category_id int primary key not null,
category_name varchar(50) not null,
KEY category_name_index (category_name)
);
From the docs (8.0 version, but the statement is true for older versions):
MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. This index might be silently dropped later, if you create another index that can be used to enforce the foreign key constraint. index_name, if given, is used as described previously.
Also, you're using a varchar(50) as your foreign key, which is not usually a great idea for a variety of reasons. You probably want to use a numeric value, such as category_id, instead.
I have three tables: ModelingAgency.clients, ModelingAgency.models, ModelingAgency.Bookings. All three tables have a primary key column called id.
The table bookings has two columns that reference clients and models. In pgAdmin when I try to create a foreign key in bookings to either clients or models I get the following screens:
What am I overlooking here? I am new to PostgreSQL (This is my first test project with PostgreSQL -- I've always used MySQL and occasionally SQL Server) so it's probably something obvious (I just don't see it).
EDIT: Here is the DDL, as requested:
-- Table: "ModelingAgency.bookings"
-- DROP TABLE "ModelingAgency.bookings";
CREATE TABLE "ModelingAgency.bookings"
(
id integer NOT NULL DEFAULT nextval('"ModelingAgency.Bookings_id_seq"'::regclass),
"clientId" integer NOT NULL,
"modelId" integer NOT NULL,
"time" timestamp with time zone NOT NULL DEFAULT now(),
"location" character varying(100) NOT NULL DEFAULT 'No Location Selected'::character varying,
CONSTRAINT "bookingId" PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE "ModelingAgency.bookings" OWNER TO "MyBatisTutorial";
-- Table: "ModelingAgency.clients"
-- DROP TABLE "ModelingAgency.clients";
CREATE TABLE "ModelingAgency.clients"
(
id integer NOT NULL DEFAULT nextval('"ModelAgency.clients_id_seq"'::regclass),
"name" character varying(45) NOT NULL,
CONSTRAINT "clientId" PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE "ModelingAgency.clients" OWNER TO "MyBatisTutorial";
-- Table: "ModelingAgency.models"
-- DROP TABLE "ModelingAgency.models";
CREATE TABLE "ModelingAgency.models"
(
id serial NOT NULL,
"name" character varying(45) NOT NULL,
CONSTRAINT "modelId" PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE "ModelingAgency.models" OWNER TO "MyBatisTutorial";
Looking into your posted DDL code I see that your table's names are written in wrong way (that causes your issue with pgAdmin):
"ModelingAgency.bookings"
It should be in format "schema"."tableName":
"ModelingAgency"."bookings"
After that Object browser looks like this (probably you need to create schema first using easily pgAdmin or with CREATE SCHEMA SQL statement):
Here is working DDL code (I omitted some things like OIDS and OWNER TO, but that doesn't matter to your case, BTW OIDS are false on default):
DROP TABLE IF EXISTS "ModelingAgency"."bookings";
CREATE TABLE "ModelingAgency"."bookings"
(
id serial,
"clientId" integer NOT NULL,
"modelId" integer NOT NULL,
"time" timestamp with time zone NOT NULL DEFAULT now(),
"location" character varying(100) NOT NULL
DEFAULT 'No Location Selected'::character varying,
CONSTRAINT "bookingId" PRIMARY KEY (id)
);
DROP TABLE IF EXISTS "ModelingAgency"."clients";
CREATE TABLE "ModelingAgency"."clients"
(
id serial,
"name" character varying(45) NOT NULL,
CONSTRAINT "clientId" PRIMARY KEY (id)
);
DROP TABLE IF EXISTS "ModelingAgency"."models";
CREATE TABLE "ModelingAgency"."models"
(
id serial NOT NULL,
"name" character varying(45) NOT NULL,
CONSTRAINT "modelId" PRIMARY KEY (id)
)