My Access database (2007) has Four tables; Customer, Supplier, Account, and AccountAgeing
AccountAgeing has a composite key made up of the foreign keys of two of the other tables, plus a date. i.e.;
AsAtDate, SupplierID, AccountNumber
I am importing data from excel via a temporary table, and my parent tables (Customers, Suppliers, Accounts) are importing well.
However importing AccountAgeing from my tempTable continually has a key violation. Of 749 possible imports, 746 violate the key. A query to test was:
SELECT DISTINCT tempTable.[SupplierID], #31/7/14#, tempTable.[AccountNumber]
FROM tempTable;
This returned 749 records (all of them). If this is the case, how do I have a key violation??
The composite key fields are all indexed, with duplicates OK. There is no data in the destination table
I have date and [Account Number] indexed as these are the fields searches will be on.
Here is a sequence of some troubleshooting steps you can try.
Remove the primary key from your target table and populate it. If you can't populate the target table, your problem may not be the key itself, and may become apparent based on error messages you receive.
If the target table does populate, try adding your desired composite key to the already populated target table.
If you are unable to add the key, re-run your "select distinct" query on the populated target table.
If you don't select 749 distinct rows, visually inspect the table contents to see what's going on.
These steps should lead you to some insight. Just a guess - but it sounds possible that you may have a data type mismatch somewhere. In cases like this, Access will sometimes convert data on the fly and insert it without giving an error. But in the process the nature of the data are changed, resulting in a key violation in the target table.
I'm curious to hear what you find. Please post a comment when you figure out what the problem is.
Hope it helps. Good luck with the troubleshooting.
Thank you Marty!! I attempted to populate manually, which errored because there was no matching record in the Customers table.
I discovered that I had incorrectly assigned AccountAgeing to be the parent of Customers, rather than of Accounts.
The business logic is that an AccountAgeing record will always have an Account, but an AccountAgeing record does not always mention Company Number (the primary key of the Customer table).
The fix was binding part of the Account Ageing composite key to the Accounts composite key.
I am unsure what will happen when I add an ATBRecord which has an account number but no Company number, but that is another question
Check the Indexed Property in table properties - make sure it is not set at Duplicates OK on any of the composite key fields
Related
In my design, I have many tables which use FKs. The issue is because certain records will be deleted and re-added at various points of time as they are linked to specific project files, the references will be always be inaccurate if I rely on the traditional auto-incrementing ID (because each time they are re-added they will be given a new ID).
I previously asked a question (Sqlite - composite PK with two auto-incrementing values) as to whether I can create a composite auto-incrementing ID however it appears to not be possible as answered by the question I was linked.
The only automatic value I can think of that'll always be unique and never repeated is a full date value, down to the second - however the idea of using a date for the tables' IDs feels like bad design. So, if I instead place a full date field in every table and use these as the FK reference, am I looking at any potential issues down the line? And am I correct in thinking it would be more efficient to store it as integer rather than a text value?
Thanks for the help
Update
To clarify, I am not looking asking in regards to Primary Keys. The PK will be standard auto-incrementing ID. I am asking in regards to basing hundreds of FKs on dates.
Thank you for the replies below, the difficulty i'm having is I can't find a similar model to learn from. The end result is i'd like the application to use project files (like Word has their docx files) to import data into the database. Once a new project is loaded, the previous project's records are cleared but their data is preserved in the project file (the application's custom file format / a txt file) so they can be added once again. The FKs will all be project-based so they will only be referencing records that exist at the time in the database. For example, as it's a world-building application, let's say a user adds a subject type that would be relevant to any project (e.g. mathematics), due to the form it's entered on in the application, the record is given a_type number of 1, meaning it’s something that persists regardless of the project loaded. Another subject type however may be Demonology which only applies to the specific project loaded (e.g. a fantasy world). A school_subject junction table needs both of these in the same table to reference as the FK. So let’s say Demonology is the second record in the subjects type table, it has an auto-increment value of 2 - thus the junction table records 2 as it’s FK value. The issue is, before this project is re-opened again, the user may have added 10 more subject types that are universal and persist, thus next time the project’s subject type records and school_subject records are added back, Demonology is now given the ID of 11. However, the school_subject junction table is re-recreated with the same record having 2 as its value. This is why I’d like a FK which will always remain the same. I don’t want all projects to be present in the database, because I want users to be able to backup and duplicate individual projects as well know that even if the application is deleted, they can re-download and re-open their project files.
This is a bit long for a comment.
Something seems wrong with your design. When you delete a row in a table, there should be no foreign key references to that key. The entity is gone. Does not exist (as far as the database is concerned). Under most circumstances, you will get an error if you try to delete a row in one table where another row refers to that row using a foreign key reference.
When you insert a row into a table, the database becomes aware of that entity. There should not be references to it.
Hence, you have an unusual situation. It sounds like you have primary keys that represent something in the real world -- such as a social security number or vehicle identification number. If that is the case, you might want this id to be the primary key of the table.
Another option is soft deletion. Once one of these rows is inserted in the table, it cannot be deleted. However, you can set a flag that says that it is deleted. Then, foreign key references can stay to the "soft" deleted row.
I am struggling with MS Access duplicate record error. I am getting this error on some of the records while doing inserts. The exact error is "The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship. Change the data in the field or fields that contain duplicate data, remove the index, or redefine the index to permit duplicate entries and try again".
The interesting part is that while running the same data set I get errors on different records each time. I removed the indexes in a destination table but still the same issue. I read that it might be MS Access glitch, so I created identical table in SQL Server and attempted the insert - worked like a charm. So it seems it is Access issue. Is there any workaround? I have tried to find one but so far no luck. Would appreciate if someone could point me to the right direction as of now changing databases would not be an option.
Thanks.
P.S. My primary key is a composite key of Name (text), Key (text) and LineNo (integer). There could be mnore than one key with the same name per each Name fields but different Line number.
So I'm working on just a learning project to expose myself to doing some things I do not get to do at work. I'm just making a simple bug and case tracking app (I know there are a million this is just to work with some tools I don't get to). So I was designing my database and realized I've never actually used Foreign Keys before in any of my projects, I've used them before but never actually setting up a column as a FK. So I've designed my database as follows, which I think is close to correct (at least for the initial layout).
Database Image http://drop.io/download/public/uurp1vxej0abpwu7jsee/895663dedff577359b900cda1726f115b24be90c/Asset/28368622/v3/large_thumbnail
However When I try to add the FK's to the linking Tables I get an error saying, "The tables present in the relationship must have the same number of columns". I'm doing this by in SQLSMS by going to the Keys 'folder' and adding a FK. Is there something that I am doing wrong here, I don't understand why the tables would have to have the same number of columns for me to add a FK relationship between the tables?
When defining a foreign key relationship there are four things you need to specify:
The referring table (foreign key table)
The columns from the referring table that will form the foreign key.
The referred table (primary key table)
The columns from the referred table that form the key.
I'm guessing that you have selected one of the above incorrectly - probably you have forgotten that you need to state the column involved in the relationship twice - once for each table.
Here's a screenshot of how it should look - note that the column is specified twice. In my example the columns have slightly different names to demonstrate that they don't always need to have the same name, but in your case the column names will be the same.
I'm defining a database for a customer/ order system where there are two highly distinct types of customers. Because they are so different having a single customer table would be very ugly (it'd be full of null columns as they are pointless for one type).
Their orders though are in the same format. Is it possible to have a CustomerId column in my Order table which has a foreign key to both the Customer Types? I have set it up in SQL server and it's given me no problems creating the relationships, but I'm yet to try inserting any data.
Also, I'm planning on using nHibernate as the ORM, could there be any problems introduced by doing the relationships like this?
No, you can't have a single field as a foreign key to two different tables. How would you tell where to look for the key?
You would at least need a field that tells what kind of user it is, or two separate foreign keys.
You could also put the information that is common for all users in one table and have separate tables for the information that is specific for the user types, so that you have a single table with user id as primary key.
A foreign key can only reference a single primary key, so no. However, you could use a bridge table:
CustomerA <---- CustomerA_Orders ----> Order
CustomerB <---- CustomerB_Orders ----> Order
So Order doesn't even have a foreign key; whether this is desirable, though...
I inherited a SQL Server database where this was done (a single column used in four foreign key relationships with four unrelated tables), so yes, it's possible. My predecessor is gone, though, so I can't ask why he thought it was a good idea.
He used a GUID column ("uniqueidentifier" type) to avoid the ambiguity problem, and he turned off constraint checking on the foreign keys, since it's guaranteed that only one will match. But I can think of lots of reasons that you shouldn't, and I haven't thought of any reasons you should.
Yours does sound like the classical "specialization" problem, typically solved by creating a parent table with the shared customer data, then two child tables that contain the data unique to each class of customer. Your foreign key would then be against the parent customer table, and your determination of which type of customer would be based on which child table had a matching entry.
You can create a foreign key referencing multiple tables. This feature is to allow vertical partioining of your table and still maintain referential integrity. In your case however, this is not applicable.
Your best bet would be to have a CustomerType table with possible columns - CustomerTypeID, CustomerID, where CustomerID is the PK and then refernce your OrderID table to CustomerID.
Raj
I know this is a very old question; however if other people are finding this question through the googles, and you don't mind adding some columns to your table, a technique I've used (using the original question as a hypothetical problem to solve) is:
Add a [CustomerType] column. The purpose of storing a value here is to indicate which table holds the PK for your (assumed) [CustomerId] FK column. Optional - addition of a check constraint (to ensure CustomerType is in CustomerA or CustomerB) will help you sleep better at night.
Add a computed column for each [CustomerType], eg:
[CustomerTypeAId] as case when [CustomerType] = 'CustomerA' then [CustomerId] end persisted
[CustomerTypeBId] as case when [CustomerType] = 'CustomerB' then [CustomerId] end persisted
Add your foreign keys to the calculated (and persisted) columns.
Caveat: I'm primarily in a MSSQL environment; so I don't know how well this translates to other DBMS (ie: Postgres, ORACLE, etc).
As noted, if the key is, say, 12345, how would you know which table to look it up in? You could, I suppose, do something to insure that the key values for the two tables never overlapped, but this is too ugly and painful to contemplate. You could have a second field that says which customer type it is. But if you're going to have two fields, why not have one field for customer type 1 id and another for customer type 2 id.
Without knowing more about your app, my first thought is that you really should have a general customer table with the data that is common to both, and then have two additional tables with the data specific to each customer type. I would think that there must be a lot of data common to the two -- basic stuff like name and address and customer number at the least -- and repeating columns across tables sucks big time. The additional tables could then refer back to the base table. As there is then a single key for the base table, the issue of foreign keys having to know which table to refer to evaporates.
Two distinct types of customer is a classic case of types and subtypes or, if you prefer, classes and subclasses. Here is an answer from another question.
Essentially, the class-table-inheritance technique is like Arnand's answer. The use of the shared-primary-key technique is what allows you to get around the problems created by two types of foreign key in one column. The foreign key will be customer-id. That will identify one row in the customer table, and also one row in the appropriate kind of customer type table, as the case may be.
Create a "customer" table include all the columns that have same data for both types of customer.
Than create table "customer_a" and "customer_b"
Use "customer_id" from "consumer" table as foreign key in "customer_a" and "customer_b"
customer
|
---------------------------------
| |
cusomter_a customer_b
We are building an application that may need to be replicated to many servers (I'm hoping not, but there's no way to know if clients will need their own client/server copy until after we release the online product).
Since the number of servers is unknown, I've decided to use GUIDs for any transactional table IDs. Since each client has their own database, I intend to use the NEWSEQUENTIALID() default, and the largest table will add no more than 1.5M rows per year (but on average 15K rows), I don't expect much of a performance problem.
However, I'm not sure how to handle cases where we want the foreign key to indicate 'none selected'. For example, a client has a single admin user. This is set up as a foreign key (login_id) to login.id (a GUID). However, if a client doesn't yet have an admin user, how would we easily set up a "None Selected" key?
In prior applications we used IDENTITY columns, and inserted a dummy entry in most tables with an ID of 0. Is there an accepted approach to providing similar functionality with a GUID?
The only safe way to do this, is set the FK value to NULL. If you need to replicate data between multiple servers, make sure each table that you replicate has GUIDs as their primary keys, foreign key relationships are this way never a problem.
Replication can work very simple this way: replicate inserts and updates first in the order of parent to child table, after that replicate the deleted records from child to parent. (reverse order.)
Hope this helps.
You have 3 options:
1) In your referenced table, add the blank value row with a guid of all zeros, then link to this record
2) Just store a null for the blank references
3) Don't have the blank records in the reference table, but store an all zero guid. This may cause problems if joins are done in in the database, or with reports. You'll have to code for this special case.
I'd say 1 and 2 are the only good options.
I might be missing something really obvious here, but can't you just set it to NULL?
Make the foreign key field in the child table NULLable and keep the field NULL when there's no admin user. Magical values like "0" identity columns is a disaster waiting to occur.