Loading...
Loading...
Design a PostgreSQL-specific schema. Covers best-practices, data types, indexing, constraints, performance patterns, and advanced features
npx skill4agent add ynulihao/agentskillos postgresql-table-designBIGINT GENERATED ALWAYS AS IDENTITYUUIDNUMERICsnake_caseUNIQUE (...) NULLS NOT DISTINCTNUMERIC(2,0)CLUSTERBIGINT GENERATED ALWAYS AS IDENTITYGENERATED BY DEFAULTUUIDuuidv7()gen_random_uuid()BIGINTINTEGERSMALLINTDOUBLE PRECISIONREALNUMERICTEXTCHECK (LENGTH(col) <= n)VARCHAR(n)CHAR(n)BYTEAPLAINEXTENDEDEXTERNALMAINEXTENDEDALTER TABLE tbl ALTER COLUMN col SET STORAGE strategyALTER TABLE tbl SET (toast_tuple_target = 4096)LOWER(col)CITEXTNUMERIC(p,s)TIMESTAMPTZDATEINTERVALTIMESTAMPnow()clock_timestamp()BOOLEANNOT NULLCREATE TYPE ... AS ENUMTEXT[]INTEGER[]@><@&&arr[1]arr[1:3]'{val1,val2}'ARRAY[val1,val2]daterangenumrangetstzrange&&@>[)INETCIDRMACADDR<<>>&&POINTLINEPOLYGONCIRCLETSVECTORTSQUERYtsvectorto_tsvector('english', col)to_tsquery('english', 'query')CREATE DOMAIN email AS TEXT CHECK (VALUE ~ '^[^@]+@[^@]+$')CREATE TYPE address AS (street TEXT, city TEXT, zip TEXT)(col).fieldvectorpgvectortimestamptimestamptzchar(n)varchar(n)textmoneynumerictimetztimestamptztimestamptz(0)timestamptzserialgenerated always as identityALTER TABLE tbl ENABLE ROW LEVEL SECURITYCREATE POLICY user_access ON orders FOR SELECT TO app_users USING (user_id = current_user_id())ON DELETE/UPDATECASCADERESTRICTSET NULLSET DEFAULTDEFERRABLE INITIALLY DEFERREDNULLS NOT DISTINCT(1, NULL)(1, NULL)NULLS NOT DISTINCT(1, NULL)NULLS NOT DISTINCTCHECK (price > 0)NOT NULLprice NUMERIC NOT NULL CHECK (price > 0)EXCLUDE USING gist (room_id WITH =, booking_period WITH &&)=<>BETWEENORDER BYWHERE a = ? AND b > ?(a,b)WHERE b = ?CREATE INDEX ON tbl (id) INCLUDE (name, email)WHERE status = 'active'CREATE INDEX ON tbl (user_id) WHERE status = 'active'status = 'active'CREATE INDEX ON tbl (LOWER(email))WHERE LOWER(email) = 'user@example.com'@>?@@CLUSTERPARTITION BY RANGE (created_at)CREATE TABLE logs_2024_01 PARTITION OF logs FOR VALUES FROM ('2024-01-01') TO ('2024-02-01')PARTITION BY LIST (region)FOR VALUES IN ('us-east', 'us-west')PARTITION BY HASH (user_id)CHECKfillfactor=90COPYINSERTBIGINT GENERATED ALWAYS AS IDENTITYUUIDON CONFLICT (col1, col2)EXCLUDED.columnDO NOTHINGDO UPDATEBEGIN; ALTER TABLE...; ROLLBACK;CREATE INDEX CONCURRENTLYNOT NULLnow()gen_random_uuid()ALTER TABLE DROP CONSTRAINTDROP COLUMNCREATE OR REPLACE... GENERATED ALWAYS AS (<expr>) STOREDVIRTUALpgcryptocrypt()uuid-ossppgcryptopg_trgm%similarity()LIKE '%pattern%'citextLOWER(col)btree_ginbtree_gisthstoretimescaledbpostgispgvectorpgauditJSONBCREATE INDEX ON tbl USING GIN (jsonb_col);jsonb_col @> '{"k":"v"}'jsonb_col ? 'k'?\|?&jsonb_col @> ANY(ARRAY['{"status":"active"}', '{"status":"pending"}'])@>jsonb_path_opsCREATE INDEX ON tbl USING GIN (jsonb_col jsonb_path_ops);??|?&@>ALTER TABLE tbl ADD COLUMN price INT GENERATED ALWAYS AS ((jsonb_col->>'price')::INT) STORED;CREATE INDEX ON tbl (price);WHERE price BETWEEN 100 AND 500WHERE (jsonb_col->>'price')::INT BETWEEN 100 AND 500@>jsonb_path_opsconfig JSONB NOT NULL CHECK(jsonb_typeof(config) = 'object')CREATE TABLE users (
user_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX ON users (LOWER(email));
CREATE INDEX ON users (created_at);CREATE TABLE orders (
order_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(user_id),
status TEXT NOT NULL DEFAULT 'PENDING' CHECK (status IN ('PENDING','PAID','CANCELED')),
total NUMERIC(10,2) NOT NULL CHECK (total > 0),
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX ON orders (user_id);
CREATE INDEX ON orders (created_at);CREATE TABLE profiles (
user_id BIGINT PRIMARY KEY REFERENCES users(user_id),
attrs JSONB NOT NULL DEFAULT '{}',
theme TEXT GENERATED ALWAYS AS (attrs->>'theme') STORED
);
CREATE INDEX profiles_attrs_gin ON profiles USING GIN (attrs);