Foreign keys referencing surrogate key has different semantics than fk referencing natural key - it is a can of worms actually and can lead to unexpected anomalies.
Lets take the example from the article (with surrogate key):
Restaurant(id, name, city)
Now let's add a possibility to record visits:
Visit(restaurant_id references Restaurant(id), user, date)
We have a procedure to register visits to a restaurant:
register_visit(restaurant_name, user_name, date_of_visit) { INSERT INTO visit SELECT id, user_name, date_of_visit FROM restaurant WHERE name = restaurant_name }
I very much enjoy spending time in "Polish Kielbasa" restaurant in Warsaw and I visit it everyday - I don't visit any other restaurant at all.
Now changes of a restaurant name will lead to the database containing misinformation:
register_visit('Polish Kielbasa', 'mkleczek', 2024-6-4); update restaurant set name = 'Old Kielbasa' where name = 'Polish Kielbasa' and city = 'Warsaw'; insert into restaurant ('Polish Kielbasa', 'Warsaw'); register_visit('Polish Kielbasa', 'mkleczek', 2024-6-4);
Question: what restaurants did I visit this year?
This kind of anomalies are avoided using _natural_ keys and - first of all - defining proper _predicate_ for _each_ relation.
The predicate of relation visit(restaurant_name, city, user, date) is quite obvious: "User [user] visited restaurant [restaurant_name] in [city] on [date]"
Question: What is the predicate of relation visit(restaurant_id, user, date)?