This is my first post and I'm a mysql noob, so I apologize for this question's length.
BACKGROUND
I have a lookup table cctypevals, with a foreign field 'cctypeID', in mysql this would be:
CREATE TABLE `cctypevals` (
`cctypevalsKEY` integer NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`cctypeID` varchar(50) NOT NULL, FOREIGN KEY(cctypeID) REFERENCES cctype(cctypeID) ,
`value` varchar(50) )
cctypeID contains field names from user tables, eg 'taskSTATE', 'serviceTYPE', 'projectCAT' etc.
The value field contains the only allowed values for these user table fields.
Thus cctypevals acts like a 'multi' keyed lookup table, for example:
select value from cctypevals where cctypeID ='serviceTYPE'
might return HomeVisit, BackToBase etc
I know it would be easier to have one lookup table per field but this is what I have.
QUESTION
How do I constrain (in a sql create table or alter statement), tables with fields like task.taskSTATE, service.serviceTYPE etc so they can only accept values from cctypevals.value where cctypeID contains the appropriate field name ?
In create or alter table statement you cannot do that, since the check constraint would be able to such things, but mysql has not implemented the check constraint yet (mysql can parse a check constraint, but it will not work).
You can create before insert and update triggers that check the specific restrictions and raise an sql error message if the updated value does not meet the requirements.
Related
I want to have an "Entity" and many versions of it, where one of those versions is the only one which is active/used. It is also possible that the Entity is entirely deactive. So I thought of using two tables with cyclic foreign keys like this:
CREATE TABLE entity (
id int NOT NULL AUTO_INCREMENT,
-- some extra irrelevant data commented out
active_version_id int DEFAULT NULL,
PRIMARY KEY (id)
);
CREATE TABLE entityversion (
id int NOT NULL AUTO_INCREMENT,
-- some extra irrelevant data commented out
entity_id int NOT NULL,
PRIMARY KEY (id)
);
ALTER TABLE entity ADD FOREIGN KEY (active_version_id) REFERENCES entityversion(id) ON DELETE SET NULL;
ALTER TABLE entityversion ADD FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE CASCADE;
I would like to, when creating a new active Entity, to create at the same time its first EntityVersion which will be its active_version. The problem is we don't have their ids yet. Currently, we're creating the Entity with "returning id" and using that to create the EntityVersion, also with "returning id", and then updating the active_version_id of that same Entity, so 3 separate commands like this for example:
INSERT INTO entity DEFAULT VALUES RETURNING id;
-- get the ID back and use it as a parameter to the next command
INSERT INTO entityversion (entity_id) VALUES (%s) RETURNING id;
-- again the same thing
UPDATE entity SET active_version_id = %s WHERE id = %s;
I would like to know if there is a shorter way to do this. I also accept as answer a different approach to the table schemas, if it happens to be the better choice. Thanks for the help!
Create both your rows in a stored procedure, or use a before insert trigger if there is no data that only goes in the entityversion version table. To deal with your cyclical id problem, in mariadb use a sequence instead of auto_increment. In mysql, emulate a sequence with an entity_sequence table that only contains the auto_increment id. In your stored procedure/trigger, get the sequence value (with insert..returning id if emulating a sequence), store entityversion using that value, then set the entityversion id to store in your entity row.
You are implying that the entities are 1:1, in which case they may as well be in the same table. (Make one of the NULLable if it is not to inserted until later.)
If it is 1:many (a 'latest' and many 'older' versions), then the FK only goes one way.
In either case, your "circular" FKs go away.
But to answer your question:
Turn off FK checks
CREATE both tables
Populate both tables
ALTER to add both FKs
Turn on FK checks.
More
Well, it seems that you have many:1, not 1:1. The "History" has a column that is the "id" into the "Current" ('active') table. No circular FKs. Index that column so you can go the other way efficiently. ON DELETE CASCADE is not practical in either direction.
The FK should go one direction, not both.
I have a database assignment where I must build the following database.
The issue is, I am given a table to create called dependent which has 5 columns. 1 of these columns is dependent_name. It can't be a Foreign Key because there is not table for the dependents, so I assume it is suppose to be a Primary Key.
When I attempted to add the data in the table I was given an error that says I cannot have duplicate values for primary key.
Of course this is because you cannot have duplicate primary keys ( Alice is a duplicate value in this situation ), but I am not sure how to get around this. I guess I could make another table called dependent_info and make the dependent_name and FK, but this is not stated in the instructions from the teacher.
Is there something I am missing here?
How can I insert new data in column after adding column without using update function. for example
"alter table Employee add column Gender varchar(1) after Birthdate then I get wrong when I used this statement insert into Employee(ENumber,EmpName,Birthdate,Address,Salary,DNumber,Gender)
-> values
-> ('E001','GSInocencio','1988-01-15','Munoz',18000,'D005','F'),
It gives me error Duplicate entry 'E001' for key 'PRIMARY'
MariaDB [Employees_Valdez]>
The messages is pretty clear: You already have an employee with that ENumber value.
You have a UNIQUE constraint on that column, it's a PRIMARY KEY, so either pick a different value, or use a different primary key.
One thing to note is MySQL doesn't use complex string primary keys very efficiently, they're also a real hassle for relating data since they're so big. It's usually better to include a standard id INT AUTO_INCREMENT PRIMARY KEY column and then have things like ENumber being a secondary UNIQUE constraint.
You can then relate data using the 4-byte id value, or 8-byte if BIGINT is a concern like you might have two billion employees.
I have a database table like this.
CREATE TABLE ItemX(
code varchar(20),
size varchar(12),
type varchar(20),
PRIMARY KEY(code),
CONSTRAINT FOREIGN KEY F1(code) REFERENCES Item(code)
);
code is similar to "xxxx-xxxx-xxxx-0001"
I need to check whether (first 15 characters of code,size,type) is unique before adding a row into the table.
I tried UNIQUE (SUBSTRING(code,1,15),size,type) but it didn't work.
How could I achieve this??
ALTER TABLE `ItemX` ADD UNIQUE `ui`(`code`, `size`, `type`);
I'm not sure if MySQL will allow you pass in a function of a column when creating a unique constraint. If you really want to use only the first 15 characters of the code column, you might want to create a new column for this purpose.
This question already has answers here:
Unique constraint that allows empty values in MySQL
(3 answers)
Closed 9 years ago.
I have an existing mysql table, and I want to set one field (varchar) so that it must either be unique, or empty (by default). So when user does not enter value, its empty, otherwise user must enter unique value.
how would I do that ?
MySQL includes a constraint type UNIQUE that allows for exactly this. If you declare a column UNIQUE and allow NULL values in it, then all values will be forced to be unique unless they are NULL values. If you want to prevent empty strings ('') from being stored, you will have to manage that at the code level, because MySQL will treat it as just another string and allow it once in a UNIQUE column. If no value is passed to such a column, it will automatically default to NULL, but you can also specify NULL (not in quotes) programmatically in your code before passing the values to the database.
For the rest of this post I will assume the name of the table is tablename and the name of the column is columnname and the size of the varchar field is 255
If you want to modify an existing table, rather than create a new one:
If the column does not already support null values:
ALTER TABLE tablename ALTER COLUMN columnname VARCHAR(255) NULL
To add the unique constraint:
ALTER TABLE tablename ADD CONSTRAINT un_tablename_column UNIQUE (columnname)`
(I always name my constraints so I can refer to them specifically later)
OR if you want to do it on a new table:
CREATE TABLE tablename (
[...]
columnname varchar(255) UNIQUE NULL,
[...]
)
From what I have read, by standard it should not be possible to have a column in a table that allowes null values AND has a unique constraint; if it is, it is down to a special mysql-engine (that will result in unpredictable/unexpected behavior elsewhere also imho)
Also your question seems kind of reverse of this one
MySQL: UNIQUE, but DEFAULT NULL - allowed by creating of table. More than 1 NULL is allowed to insert. Why?
You could however enforce this using triggers, you can write a trigger on insert/update to check if the value already exists and immediatly delete it if it does.
I think you better process your data before pass to mysql, or not, you can write a trigger trigger whenever your table is update to make sure it pass your rule