I have a table with a unique constraint on event_time and card_nr, nevertheless, I'm still able to insert duplicate values to the table using the statements below.
The screenshot below shows the table I used as well as my DDL & insert queries.
There is also an EXPLAIN statement to prove that the columns are unique.
An error should be thrown since I'm violating my constraint values?
Supported Constraint Types
Snowflake supports the following constraint types from the ANSI SQL standard:
UNIQUE
PRIMARY KEY
FOREIGN KEY
NOT NULL
...
Snowflake supports defining and maintaining constraints, but does not enforce them, except for NOT NULL constraints, which are always enforced.
What is the point of supporting a unique constraint but not enforcing it?
Constraints
Constraints are provided primarily for data modeling purposes and compatibility with other databases, as well as to support client tools that utilize constraints. For example, Tableau supports using constraints to perform join culling (join elimination), which can improve the performance of generated queries and cube refresh.
Related
Is there a way for constraints to actually work in Snowflake?
A primary key is created. Still duplicates can be inserted in the table. Giving options like cascade update and delete cascade are not working with Foreign key
Can someone please help?
if you read the Snowflake documentation you will see that only NOT NULL constraints are enforced, all other constraint types are informational only.
I am guessing that the reason for this is that Snowflake is an analytical, rather than an OLTP, database and therefore the expectation is that constraints are enforced in your ELT processes (as is normal practice) rather than in the DB.
Snowflake does not enforce constraints except not null.
Snowflake Notes . I think we cannot enforce a constraint in snowflake database but you can apply the constraint in your ETL tool(if using)
Snowflake allows UNIQUE, PRIMARY KEY, FOREIGN KEY and NOT NULL constraints but I read that it enforces only NOT NULL constraint. Then what is the purpose of other keys and under what circumstances do we have to define them? I appreciate any examples.
Thank you,
Prashanth.
They express intent, helping people understand your data models. Data modeling tools can use them to generate diagrams. You can also programmatically access them to validate data integrity yourself.
Constraints
Snowflake supports defining and maintaining constraints, but does not enforce them, except for NOT NULL constraints, which are always enforced.
Constraints are provided primarily for data modeling purposes and compatibility with other databases, as well as to support client tools that utilize constraints. For example, Tableau supports using constraints to perform join culling (join elimination), which can improve the performance of generated queries and cube refresh.
Constraints could also improve the query performance:
Extended Constraint Properties
RELY | NORELY
Specifies whether a constraint in NOVALIDATE mode is taken into account during query rewrite.
By default, this constraint property is set to NORELY.
If you have ensured that the data in the table does comply with the constraints, you can change this to RELY to indicate that the query optimizer should expect the data in the table to adhere to the constraints. Setting this can improve query performance (e.g. by eliminating unnecessary joins).
Understanding How Snowflake Can Eliminate Redundant Joins
In some cases, a join on a key column can refer to tables that are not needed for the join. If your tables have key columns and you are using and enforcing the UNIQUE, PRIMARY KEY, and FOREIGN KEY constraints, Snowflake can improve query performance by eliminating unnecessary joins on key columns.
Eliminating an Unnecessary Left Outer Join
Eliminating an Unnecessary Self-Join
Eliminating an Unnecessary Join on a Primary Key and Foreign Key
Do database engines utilize foreign keys transparently or a query should explicitly use them?
Based on my experience there is no explicit notion of foreign keys on a table, except that a constraint that maintains uniqueness of the key and the fact that the key (single or a group of fields) is a key which makes search efficient.
To clarify this, here is an example why it is important: I have a middleware (in particular ArcGIS for my case), for which I can control the back-end database (so I can create keys, indices, etc.) and I usually use the front (a RESTful API here). The middleware itself is a black box and to provide effective tools to take advantage of the underlying DBMS's capabilities. So what I want to understand is that if I build foreign key constraints and use queries that if implemented normally would translate into queries that would use those foreign keys, should I see performance improvements?
Is that generally the case or various engines do it differently? (I am using PostgresSQL).
Foreign keys aren't there to improve performance. They're there to enforce data integrity. They will decrease performance for inserts/updates/deletes, but they make no difference to queries.
Some DBMSs will automatically add an index to the foreign key field, which may be where the confusion is coming from. Postgres does not do this; you'll need to create the index yourself. (And yes, the database will use this index transparently.)
As far as I know Database engines needs specific queries to use foreign keys. You have to write some sort of join queries to get data from related tables.
However some Data access framework hides the complexity of accessing data from foreign keys by providing transparent way of accessing data from related tables but I am not sure that may provide much improvement in performance.
This is completely depends on the database engine.
In PostgreSQL constraints won't cause performance improvements directly, only indexes will do that.
CREATE INDEX is a PostgreSQL language extension. There are no provisions for indexes in the SQL standard.
However, adding some constraints will automatically create an index for that column(s) -- f.ex. UNIQUE & PRIMARY KEY constraints creates a btree index on the affected column(s).
The FOREIGN KEY constraint won't create indexes on the referencing column(s), but:
A foreign key must reference columns that either are a primary key or form a unique constraint. This means that the referenced columns always have an index (the one underlying the primary key or unique constraint); so checks on whether a referencing row has a match will be efficient. Since a DELETE of a row from the referenced table or an UPDATE of a referenced column will require a scan of the referencing table for rows matching the old value, it is often a good idea to index the referencing columns too. Because this is not always needed, and there are many choices available on how to index, declaration of a foreign key constraint does not automatically create an index on the referencing columns.
First, I want to talk a little about the Foreign key constraint rule and how helpful it is. Suppose I have two tables, a primary table with the primary column called ID, the other table is the foreign one which also has a primary column called ID. This column in the foreign table refers to the ID column in the primary table. If we don't establish any Foreign key relation/constraint between those tables, we may fall foul of many problems related to integrity.
If we create the foreign key relation for them, any changes to the ID column in primary table will 'auto' reflect to the ID column in the foreign table, changes here can be made by DELETE, UPDATE queries. Moreover, any changes to the ID in the foreign table should be constrained by the ID column in the primary table, for example there shouldn't any new value inserted or updated in the ID column of the foreign table unless it does exist in the ID column of the primary table.
I know that SQLite doesn't support foreign key constraint (with full functions as detailed above) and I have to use TRIGGER to work around this problem. I have used TRIGGER to work around successfully in one way (Any changes to the ID column in the primary table will refect to the ID column in the foreign table) but the reverse way (should throw/raise any error if there is a confict occurs, for example, there are only values 1,2,3 in the ID column of the primary table, but the value 2 in the ID column of the foreign table is updated to 4 -> not exist in the primary table -> should throw error) is not easy. The difficult is SQLite doesn't also support IF statement and RAISERROR function. If these features were supported, I could work around easily.
I wonder how you can use SQLite if it doesn't support some important features? Even working around by using TRIGGER is not easy and I think it's impossible, except that you don't care about the reverse way. (In fact, the reverse way is not really necessary if you set up your SQL queries carefully, but who can make sure? Raising error is a mechanism reminding us to fix and correct and making it work exactly without corrupting data and the bugs can't be invisible.
If you still don't know what I want, I would like to have some last words, my purpose is to achieve the full functionality of the Foreign key constraint which is not supported in SQLite (even you can create such a relationship but it's fake, not real as you can benefit from it in SQL Server, SQL Server Ce, MS Access or MySQL).
Your help would be highly appreciated.
PS: I really like SQLite because it is file-based, easy to deploy, supports large file size (an advantage over SQL Server Ce) but some missing features have made me re-think many times, I'm afraid if going for it, my application may be unreliable and corrupt unpredictably.
To answer the question that you have skillfully hidden in your rant:
SQLite allows the RAISE function inside triggers; because of the lack of control flow statements, this must be used with a SELECT:
CREATE TRIGGER check_that_id_exists_in_parent
BEFORE UPDATE OF id ON child_table
FOR EACH ROW
BEGIN
SELECT RAISE(ABORT, 'parent ID does not exist')
WHERE NOT EXISTS (SELECT 1
FROM parent_table
WHERE id = NEW.id);
END;
Hi I've set up two very basic tables. One table will act as a look up, with an identity field as a primary key. The other table uses the look up ID as a foreign key.
I have created a relationship constraint so now I cannot delete from the look up if the foreign key is used in the "main" table.
However my issue is i can add a record with a foreign key that doesn't exist.
To my way of thinking this shouldn't be allowed, can anyone tell me what setting I need to use to enforce this and whether this is typical database design or not?
Thanks Dave
You way of thinking is correct. Good database design provides some way of enforcing what is called "Referential Integrity". This is simply a buzzword for the concept you have derived on your own. Namely that a foreign key should be rejected if it refers to a non existent row. For a general discussion of referential integrity, see the following Wikipedia article. It's short.
http://en.wikipedia.org/wiki/Referential_integrity
Some pprogrammers would like to enforce referential integrity inside their programs. In general, it's a much better plan to define a referential integrity constraint inside the database, and let the DBMS do the enforcement. It's easier, it's faster, and it's more effective.
The SQL Data Definition Language (DDL) provides a way to declare a foreign key constraint when you create a table. The syntax differs a little between different dialects of SQL, but it's basically the same idea in all of them. Here's a capsule summary.
http://www.w3schools.com/sql/sql_foreignkey.asp
The documentation for SQL Server should have a description of the referential integrity constraint under the CREATE TABLE command.