SQLite, how to entities associations without foreign keys? - database

I am trying to figure out the way of creating table without a foreign key under sqlite. I would like to avoid the use of foreign key due its incompatibility under some applications I am working now.
Could anyone please show a simple example with maybe two tables? Thank you.
Simple example: How do I select all tracks from one specific artist?
CREATE TABLE artist(
artistid INTEGER PRIMARY KEY,
artistname TEXT
);
CREATE TABLE track(
trackid INTEGER,
trackname TEXT,
trackartist INTEGER
);

You can have relationships between tables without declaring a foreign key. You simply do
SELECT a.*, t.* FROM artist a INNER JOIN track t ON a.artistid = t.trackartist;
(substituting the actual columns you want in place of a.*, t.*).
You can do this without declaring that trackartist is a foreign key to artist(artistid). If you do make that declaration, the difference is that SQLite will ensure that you never put a value in trackartist that is not a valid artistid and that you never change or remove an artistid that is used in trackartist.
Foreign keys are a mechanism to maintain the integrity of the association between tables but you can "create" any association you want in a SELECT statement independent of any primary or foreign keys declared in the database.

If you don't specify a foreign key, then there is no foreign key.
SELECT t.trackname, t.trackid
FROM track t
INNER JOIN artist a
ON a.artistid = t.trackartist
WHERE a.artistname = 'Alex'

Related

Postgres INSERT INTO... SELECT violates foreign key constraint

I'm having a really, really strange issue with postgres. I'm trying to generate GUIDs for business objects in my database, and I'm using a new schema for this. I've done this with several business objects already; the code I'm using here has been tested and has worked in other scenarios.
Here's the definition for the new table:
CREATE TABLE guid.public_obj
(
guid uuid NOT NULL DEFAULT uuid_generate_v4(),
id integer NOT NULL,
CONSTRAINT obj_guid_pkey PRIMARY KEY (guid),
CONSTRAINT obj_id_fkey FOREIGN KEY (id)
REFERENCES obj (obj_id)
ON UPDATE CASCADE ON DELETE CASCADE
)
However when I try to backfill this using the following code, I get a SQL state 23503 claiming that I'm violating the foreign key constraint.
INSERT INTO guid.public_obj (guid, id)
SELECT uuid_generate_v4(), o.obj_id
FROM obj o;
ERROR: insert or update on table "public_obj" violates foreign key constraint "obj_id_fkey"
SQL state: 23503
Detail: Key (id)=(-2) is not present in table "obj".
However, if I do a SELECT on the source table, the value is definitely present:
SELECT uuid_generate_v4(), o.obj_id
FROM obj o
WHERE obj_id = -2;
"0f218286-5b55-4836-8d70-54cfb117d836";-2
I'm baffled as to why postgres might think I'm violating the fkey constraint when I'm pulling the value directly out of the corresponding table. The only constraint on obj_id in the source table definition is that it's the primary key. It's defined as a serial; the select returns it as an integer. Please help!
Okay, apparently the reason this is failing is because unbeknownst to me the table (which, I stress, does not contain many elements) is partitioned. If I do a SELECT COUNT(*) FROM obj; it returns 348, but if I do a SELECT COUNT(*) FROM ONLY obj; it returns 44. Thus, there are two problems: first, some of the data in the table has not been partitioned correctly (there exists unpartitioned data in the parent table), and second, the data I'm interested in is split out across multiple child tables and the fkey constraint on the parent table fails because the data isn't actually in the parent table. (As a note, this is not my architecture; I'm having to work with something that's been around for quite some time.)
The partitioning is by implicit type (there are three partitions, each of which contains rows relating to a specific subtype of obj) and I think the eventual solution is going to be creating GUID tables for each of the subtypes. I'm going to have to handle the stuff that's actually in the obj table probably by selecting it into a temp table, dropping the rows from the obj table, then reinserting them so that they can be partitioned properly.

SQL Server choosing foreign key from another foreign key or unique key

In my scenario I have a table tblCity that has two columns as foreign keys CompanyRef and BranchRef, also they together are unique.
And I'd add one unique key to use as primary key [ID]
And in other table called tblCustomer I need to use tblCity as foreign key.
My problem is that I really need that ID column or I should use two foreign keys as primary key? In second case I must use three column as foreign key (CompanyRef, BranchRef, CityRef) in tblCustomer or what?
Which one of these methods is right for my problem?
So, just to make things clear a little bit in your question (I hope I got it right):
tblCity
CityId INT -- is part of the separate PK option
CompanyRef INT, FK -> tblCompany
BranchRef INT, FK -> tblBranch
tblCustomer
CustomerId INT -- not interesting here
CityRef INT FK -> tblCity -- is part of the separate PK option
CompanyRef INT -- part of the alternative
BranchRef INT -- part of the alternative
I can't tell which one is best performance-wise (that's more a DBA question), but from a developer perspective, I would advice for having a single column PK for City:
City sounds like a quite generic concept. It might be needed in the future, so dragging two columns in each other table referencing it, means that each JOIN will be on those two columns.
The final solution could look like this:
tblCity
CityId INT PRIMARY KEY IDENTITY(1, 1),
CompanyRef INT, FK -> tblCompany
BranchRef INT, FK -> tblBranch
UNIQUE (CompanyRef, BranchRef) -- acts as a constraint, but also an index
tblCustomer
CustomerId INT
CityRef INT FK -> tblCity
Side note: Hungarian notation seems quite discouraged these days - see this very popular question and its answers.
Also, I would advice to keep the same column name for the same thing. E.g.
CompanyRef -> CompanyId (or whatever the PK is named)
BranchRef -> BranchId
you need to creat relationship
base of what type of relationship you need to use
primary key and foreign key = one to money
primary key and primary key = one to one
foreign key and foreign key = many to many

Can one attribute have two foreign keys?

Just doing some Relational Database work.
Quick question, can one attribute have two foreign keys?
For example, is this legal:
PERSONAL_RECORDS.Date_of_birth has a foreign key in CASUAL.Date_of_birth as well as a foreign key in MANAGER.Date_of_birth
Basically, can one attribute, have a foreign key from two other attributes?
Thank you in advance! :)
A single column can reference more than one table.
create table t1 (
t1_id integer primary key
);
create table t2 (
t2_id integer primary key
);
create table t3 (
t3_id integer primary key,
foreign key (t3_id) references t1 (t1_id),
foreign key (t3_id) references t2 (t2_id)
);
Tricky question actually, i would read: http://office.microsoft.com/en-us/access-help/design-the-tables-for-a-new-database-RZ101772996.aspx?section=9 for a bit more information on the subject. From what i recall from the schoolbench, it's not possible. But there might be a way to do it?
Multiple Foreign keys to a single table and single key pointing to more than one table also goes into a little detail regarding this.
Good luck though :)

Varchar datatype as primary key in in many-to-many relationship

I have a table with a varchar datatype as the primary key. I'm trying to make a relationship to the junction table of this many-to-many relationship. I keep getting the error
The ALTER TABLE statement conflicted with the foreign key constraint
relationship name.
I don't know what the deal is here. Since I have designated the field as a primary key and it was accepted, this means there are no dupes. Both the foreign key and the primary key are of the same datatype, with the same length. Neither one allows nulls. What else could the problem be?
Most likely, you have a value in your junction table that does not exist in the primary table, which prevents you from creating the foreign key relationship.
Try to find it with something like:
SELECT j.ICD_FK
FROM ICD_Junction j
LEFT JOIN ICD_text t
ON j.ICD_FK = t.ICD_ID
WHERE t.ICD_ID IS NULL;
Just because there are no nulls or duplicates does not mean that you're not violating a foreign key relationship.
I'm guessing that the FK column has values in it that do not exist in the PK column. Check by using a LEFT OUT JOIN WHERE NULL.

Are foreign keys indexed automatically in SQL Server?

Would the following SQL statement automatically create an index on Table1.Table1Column, or must one be explicitly created?
Database engine is SQL Server 2000
CREATE TABLE [Table1] (
. . .
CONSTRAINT [FK_Table1_Table2] FOREIGN KEY
(
[Table1Column]
) REFERENCES [Table2] (
[Table2ID]
)
)
SQL Server will not automatically create an index on a foreign key. Also from MSDN:
A FOREIGN KEY constraint does not have
to be linked only to a PRIMARY KEY
constraint in another table; it can
also be defined to reference the
columns of a UNIQUE constraint in
another table. A FOREIGN KEY
constraint can contain null values;
however, if any column of a composite
FOREIGN KEY constraint contains null
values, verification of all values
that make up the FOREIGN KEY
constraint is skipped. To make sure
that all values of a composite FOREIGN
KEY constraint are verified, specify
NOT NULL on all the participating
columns.
As I read Mike's question, He is asking whether the FK Constraint will create an index on the FK column in the Table the FK is in (Table1). The answer is no, and generally. (for the purposes of the constraint), there is no need to do this The column(s) defined as the "TARGET" of the constraint, on the other hand, must be a unique index in the referenced table, either a Primary Key or an alternate key. (unique index) or the Create Constraint statment will fail.
(EDIT: Added to explicitly deal with comment below -)
Specifically, when providing the data consistency that a Foreign Key Constraint is there for. an index can affect performance of a DRI Constraint only for deletes of a Row or rows on the FK side. When using the constraint, during a insert or update the processor knows the FK value, and must check for the existence of a row in the referenced table on the PK Side. There is already an index there. When deleting a row on the PK side, it must verify that there are no rows on the FK side. An index can be marginally helpful in this case. But this is not a common scenario.
Other than that, in certain types of queries, however, where the query processor needs to find the records on the many side of a join which uses that foreign key column. join performance is increased when an index exists on that foreign key. But this condition is peculiar to the use of the FK column in a join query, not to existence of the foreign Key constraint... It doesn't matter whether the other side of the join is a PK or just some other arbitrary column. Also, if you need to filter, or order the results of a query based on that FK column, an index will help... Again, this has nothing to do with the Foreign Key constraint on that column.
No, creating a foreign key on a column does not automatically create an index on that column. Failing to index a foreign key column will cause a table scan in each of the following situations:
Each time a record is deleted from the referenced (parent) table.
Each time the two tables are joined on the foreign key.
Each time the FK column is updated.
In this example schema:
CREATE TABLE MasterOrder (
MasterOrderID INT PRIMARY KEY)
CREATE TABLE OrderDetail(
OrderDetailID INT,
MasterOrderID INT FOREIGN KEY REFERENCES MasterOrder(MasterOrderID)
)
OrderDetail will be scanned each time a record is deleted in the MasterOrder table. The entire OrderDetail table will also be scanned each time you join OrderMaster and OrderDetail.
SELECT ..
FROM
MasterOrder ord
LEFT JOIN OrderDetail det
ON det.MasterOrderID = ord.MasterOrderID
WHERE ord.OrderMasterID = #OrderMasterID
In general not indexing a foreign key is much more the exception than the rule.
A case for not indexing a foreign key is where it would never be utilized. This would make the server's overhead of maintaining it unnecessary. Type tables may fall into this category from time to time, an example might be:
CREATE TABLE CarType (
CarTypeID INT PRIMARY KEY,
CarTypeName VARCHAR(25)
)
INSERT CarType .. VALUES(1,'SEDAN')
INSERT CarType .. VALUES(2,'COUP')
INSERT CarType .. VALUES(3,'CONVERTABLE')
CREATE TABLE CarInventory (
CarInventoryID INT,
CarTypeID INT FOREIGN KEY REFERENCES CarType(CarTypeID)
)
Making the general assumption that the CarType.CarTypeID field is never going to be updated and deleting records would be almost never, the server overhead of maintaing an index on CarInventory.CarTypeID would be unnecessary if CarInventory was never searched by CarTypeID.
According to: https://learn.microsoft.com/en-us/sql/relational-databases/tables/primary-and-foreign-key-constraints?view=sql-server-ver16#indexes-on-foreign-key-constraints
Unlike primary key constraints, creating a foreign key constraint does not automatically create a corresponding index

Resources