Foreign key: check table has no key field with the domain - abap

I have two tables: ZDEPARTMENT01 and ZEMPLOY01.
ZDEPARTMENT01 has a foreign key DEPHEAD, whose data element is ZPERSONNEL_NO of domain ZPERSONNEL_NO ( NUMC, 10 ). ZEMPLOY01 has a primary key EMP_NUM, whose data element is ZEMP_NUM of domain ZEMP_NUM ( NUMC, 10 ).
ZDEPARTMENT01-DEPHEAD is the foreign key and ZEMPLOY01-EMP_NUM is the check key, and ZDEPARTMENT01-DEPHEAD domain ZPERSONNEL_NO has value table: ZEMPLOY01.
While setting the check table for ZDEPARTMENT01-DEPHEAD I got the error Check table ZEMPLOY01 has no key field with the domain ZPERSONNEL_NO of the field DEPHEAD
Even though both domains have the same datatype and length (but different domains) the system is unable to recognize the foreign key table and check table relationship.
The document says: The system attempts to assign the key fields of the check table to fields of the table with the same domain. Does it mean in addition to the datatype and the length, the domain names should be same between the foreign key table and the check table?
How to solve this?

Yes that's what it means. You have two Data Elements: ZEMP_NUM and ZPERSONNEL_NO. If you double-click on these, in your table, you will navigate to the data element definition. There you will see the Domain assigned to each. These should be the same, so make them the same.
Think about it this way:
Domains provide structural consistency for data that can appear in multiple places. You wouldn't have an employee id that's 10 digits in some places and 8 in others or it will cause 10-digit records to get truncated. Likewise, if you run out of digits and need to extend your employee id to 11 digits, you want to make sure it's changed everywhere, in every table where it's used. Domains let you do this. Domains also let you configure the default look up relationship (value table) or fixed values that can be selected (eg the Employee table).
Data Elements provide contextual relevance. You'll notice that in addition to supplying the domain of a data element, you can define the field labels and heading, and you can assign a custom search help. These allow you to display the field to the user in a way that is relevant to the current activity. In this case, you can label the Employee "Department Head", because it would be confusing to have a field meant to hold the ID of the department head and have it display as only "Employee". You could also add a search help that restricts the Employee list to only those flagged as "Managers".

As it already says in the message, you'll have to adjust your data elements to use the same domains:
The check table must have a key field to which the domain of the check
field is assigned.
(documentation)
I'm not entirely sure about this, but I believe the rationale behind this is that this will prevent you from changing one of the table field definitions without changing the other one at the same time.

I think your problem are the key fields definitions. The table 'ZEMPLOY01' has the key fields 'CARRIER' and 'EMPNUM' and if you want that the foreign key 'DEPHEAD' of table 'ZDEPARTMENT01' works then you have two options:
Change the key fields defined in table 'ZEMPLOY01'. Just set 'EMPNUM' as your only key field and then try to make the relation.
Add the field 'CARRIER' to table 'ZDEPARTMENT01' and then try to make the relation.
Please confirm.
Hope it helps.

Related

Using foreign keys to limit values allowed in a field based on values in another field

I have a database table whose records are "sales", with one of the fields being "Country" (where the sale occurred).
I want to make sure people can only enter a valid country name (e.g., Republic of Korea vs South Korea). I can't do this with a CHECK constraint since it's not a fixed value check or based on another value in the row.
However, I do think it's a good candidate for using a foreign key constraint:
Create a new table 'countries' where the country name is the primary key (we could also include other fields like 'population', 'currency_code' etc if we wanted, but that is tangential to my question).
Make the "Country" field in my 'sales' table a foreign key, with reference to the "country_name" primary key in "countries" table.
This would not only enforce consistent naming (or presentation of a pick-list if using a UI) but also further normalize our data (now country-level data can be stored in one place).
Is there another way to enforce these type of 'pick-list' constraints, where the pick list can be dynamic (based on another table that may be updated)?
My only concern with my approach is that if we change a country name, we could wreak havoc with the sales table. Maybe a better approach is to change the field in "sales" from "country" to "country_id" and then create a UUID for each country in the country table. This way, the user could still look up which id they want to use (again, perhaps via a graphical pick list) but we won't break the tables if we re-name the country.
Suggestions?
You are correct that having a separate Country table would be the more normalized and flexible approach, but a field whose value may potentially change is never a good candidate to be a primary key -- that's usually a red flag that you've chosen the wrong field for your primary key.
A hybrid approach is for your Country table's primary key could be something like a "CountryCode" or "CountryIdentifier", which could be a small character field that could hold an abbreviation or shortened name that you use like an identifier, use that same value as your foreign key in your Sales table. Then the full Country name could be one of the additional fields you normalize in the Country table, which could change when necessary, and could be displayed in your UI, but if you ever needed to look at your data directly, you have something a little more readable that an number or UUID.

Composite Key in Access 2016

I'm creating those auxiliary tables, that stores two foreing keys, for a N:N relationship.
I dont want to create another field just for primary key. I want to use both of them as PK.
If a mark both fields as NEEDED and EXCLUSIVE, they'll meet all PK requirements?
No. What you need is to create a unique index holding the two fields, then mark this as the Primary Key.
Other way to solve this problem without using auxiliary table is Lookup fields.
You limit the possible values to a list or a table and those will appear in a dropbox.
And with just a check box in the wizard, you now have a multiple value field.
1) Select your table
2) Select design view mode
3) Select "Lookup Assistance", in the Data Type colunm of the field you want to change.
4) Follow the wizard.
Hint, its better to get the values from a table than from a non-structured list.
It'll ease future changes or the insertion of new values.

Table Structure (Missing Primary Key)

I'm developing an online shop application which includes a table named 'tbl_items'. The primary key for each item is the 'item_id' field.
Now, I want to add an option for each item posted on the shop to be associated with multiple pictures describing the item (unlimited amount of pictures per item), so I created another table called 'tbl_item_pictures' which includes two columns - 'item_id' and the url of the picture (varchar with the size of 2083).
I believe this structure isn't the best and it might be due to the fact it's already late where I live and I just can't think of any better solution, but I'm kind of lost. I would really not like to leave the table without a primary key, nor I want to assign a primary key to both of my fields.
Any ideas of what I can add/change in my current structure to make this work?
This is a very common design pattern, and putting both columns into a PK is the normal solution. If you don't do this you will potentially have multiple links from an item to the same picture.
There's nothing wrong with putting both columns into a PK for this.
Update:
to recap....
1 - Put your pictures into their own table, with an ID column and the url.
2 - In your linking table, use tbl_itemID and pictureID, and have them both be part of the PK for the lookup table.
You have 3 possibilities:
1.) Have no primary key. atm you seem not to need one.
2.) If item_id and url are unique together use both as primary key
3.) add a third column (like picture_id) and fill it manually or automatically from a sequence
Good luck!
I would make the item_id the foreign key in the pictures table. It's ok if there's not a primary key, unless you just want to add an additional autonumber column to have that distinction.
However, the say you have it is fine. Every picture has its individual item_id it's attached to.
Think of it as a simple lookup table.

SQL Newbie: Use a foreign key for a lookup table being used like an enum() field?

Say I have field Ice_Cream.flavor, with the current choices in lookup table Flavor.flavor.
I use Flavor.flavor like an enum() list, storing the value, not the record ID, in Ice_Cream.flavor. If Flavor.flavor changes, I don't want to update Ice_Cream:flavor. I want it to stay as created.
Should I set up Ice_Cream.Flavor as a foreign key, so I can see the source of the values in my ER diagram, or not?
If you want Ice_Cream.flavor to stay as created even if there is no matching record in Flavor (which is what your question sounds like) then you cannot create a FOREIGN KEY relationship, it will not allow that condition to occur in your database.
Furthermore, if you're storing the actual text Flavor.Flavor string in Ice_Cream.Flavor, there's no particular reason to have a separate RecordID column in Flavor.
IMHO, you do not need a FK here except if you have additional informations about a flavor in the Flavor table beside the name in the column flavor. It is the case because you do not keep an ID, you keep the name AND you want to keep the old value.
I also supposed that you do not want to keep old flavors in the Flavor table or elsewhere except in the Ice_Cream table.
Last but not least, a FK would require that any flavor stored in Ice_Cream.flavor exists in the Flavor table. It is not the case if I understand correctly your question.

Normalization in sql

How would i go normalize the table that has duplicate tuples?
--------------------------------------
ID | Name | Email
-----------------------------------------
1 | John | user#somedomainname
2 | John | user#somedomainname
In this case two users have same name and email.
If it has duplicate tupes it can't have a Primary Key. This is required for first normal form.
Brax: First, look closely at the entities your table is describing. Duplicate information is a common sign that you're storing two (or more) entities in the same table. Then split these out. Write a query using group by, or distinct, or some application logic to find the unique values. Ensure this by using unique constraints where appropriate. Ensure these entities have a primary key.
Second: add foreign key columns to your existing table, so that it can form a relation to the new table(s) you just created. Fill the foreign key table.
Third: Drop the columns containing the information you just offloaded to the separate entity table(s).
Since your question is very generic, so is this answer... but I hope it helps at least a little bit.
Make the fields which form the tuple a Primary Key.
Are these users assumed to be the same person? Perhaps user 1 registered, then maybe abandoned that email address or entered it incorrectly, then user 2 used the same details). If they are assumed to be different people, you need to add additional data to uniquely identify them e.g. date of registration.
Assuming that the two users are the same person, first, decide which of the two rows you want to keep (for example, always choose the one with the lowest ID, so in this case its 1). Then find all rows in other tables that reference the row you want to remove (in this case, its 2). Update all of these Foreign Keys so they point to 1 instead. Then, you can delete the row that has ID = 2.
Now that you have tidied up the data, you should amend your schema to prevent this from happening again: put a unique constraint on Name and Email (or even just on Email if you should not allow the same email to be used by two people).