Quantcast
Channel: User Schwern - Stack Overflow
Viewing all articles
Browse latest Browse all 581

Answer by Schwern for What is the typical method for preventing duplicates in a PostgreSQL table?

$
0
0

Create a unique index on name and ingredients.

create unique index recipe_uniq_idx on recipe(name, ingredients);

This only works if the ingredients are exactly the same, in the same order.

This also acts as an index on name. ingredients should have its own gin index.

For the primary key, use a normal integer primary key. Why? Consider if you used (name, ingredients) as the primary key. Everything which wants to reference a row has to copy the name and all the ingredients; this is awkward and slow. Same if you wish to refer to a recipe in a URL. A simple integer makes references simple and small.


However, while arrays are tempting it's usually better to store lists as a join table. Most databases don't support arrays, so it's a bit of a dead end. They make querying non-standard. You can't attach more data to them, don't ingredients in a recipe need portions?

create table recipes (  id serial primary key,  name text not null,  calories int not null,  -- Don't name a column "date", that's a keyword and it doesn't explain  -- what the date is for. Use timestamp for the extra accuracy, you can  -- always convert it to a date.  created_at timestamp not null default now());create table recipe_ingredients (  recipe_id integer not null references recipes,  name text not null,  unit text not null,  portion numeric(6,2) not null);select r.name, array_agg(ri.name)from recipes rjoin recipe_ingredients ri on r.id = ri.recipe_idgroup by r.id

This does make it more difficult to detect duplicates. You can check before inserting like so:

select r.id, r.name, array_agg(ri.name) as ingredientsfrom recipes rjoin recipe_ingredients ri on r.id = ri.recipe_idgroup by r.idhaving array_agg(ri.name) @> $1 and array_agg(ri.name) <@ $1

Demonstration.


Viewing all articles
Browse latest Browse all 581


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>