I have a problem collecting data from an SQL database that I designed.
This is a table of questions of different types, each type has it's own table with different columns and has the questionid as a foreign key that referenced this table as seen below.
Column | Type | Modifiers
------------+------------------------+-----------
questionid | integer | not null
header | character varying(500) |
Indexes:
"quizquestion_pkey" PRIMARY KEY, btree (questionid)
Referenced by:
TABLE "matchingpairs" CONSTRAINT "matchingpairs_questionid_fkey" FOREIGN KEY (questionid) REFERENCES quizquestion(questionid)
TABLE "mcqchoices" CONSTRAINT "mcqchoices_questionid_fkey" FOREIGN KEY (questionid) REFERENCES quizquestion(questionid)
TABLE "questionsinquiz" CONSTRAINT "questionsinquiz_questionid_fkey" FOREIGN KEY (questionid) REFERENCES quizquestion(questionid)
TABLE "truefalsequestion" CONSTRAINT "truefalsequestion_questionid_fkey" FOREIGN KEY (questionid) REFERENCES quizquestion(questionid
)
I have another table that keeps up which question belongs to which quiz using also the questionid
Column | Type | Modifiers
------------+---------+-----------
quizid | integer | not null
questionid | integer | not null
index | integer |
Indexes:
"questionsinquiz_pkey" PRIMARY KEY, btree (quizid, questionid)
Foreign-key constraints:
"questionsinquiz_questionid_fkey" FOREIGN KEY (questionid) REFERENCES quizquestion(questionid)
"questionsinquiz_quizid_fkey" FOREIGN KEY (quizid) REFERENCES quiz(quizid)
Is there a way to collect all the different questions in one query or do I have to query on every question type, or is there something different that I can change in the database table design.
Based on your description, you can use Postgres inheritance. This is a facility where tables can be related to each other. The place to start learning about it is in the documentation.
Using inheritance, you would have a parent table called questions which defines questionId and other related columns. Then you can define multiple other tables such as matchingPairsQuestions which inherit from questions. Queries and foreign keys can then refer either to the individual "children" tables or to all of them as a single set.
Related
I have two mysql tables. The first one is created using the following code:
create table project(
project_id int not null auto_increment,
project_name varchar(30)
primary key(project_id));
The second table:
create table matches(
match_id int not null auto_increment,
match_name varchar(30),
project_id int(4) foreign key (project_id) references projects(project_id));
Both these commands works fine. I want to add the project_name column from the first table to the second table. I tried using
alter table projects drop primary key, add primary key(project_id, project_name);
and then
alter table matches add column project_name varchar(30), add foreign key (project_name) references projects(project_name);
But got the following error:
ERROR 1005 (HY000): Can't create table 'matches.#sql-55e_311' (errno: 150)
How do i include both the columns from the first table into the second table.
The current structure of my second table is as follows:
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| match_id | int(11) | NO | PRI | NULL | auto_increment |
| match_name | varchar(30) | YES | | NULL | |
| project_id | int(4) | NO | MUL | NULL | |
+------------+-------------+------+-----+---------+----------------+
I want to add the project_name as the fourth column in my second table.
To use a compound Primary Key as Foreign Key, you'll have to add the
same number of columns (that compose the PK) with same datatypes to
the child table and then use the combination of these columns in the
FOREIGN KEY definition.
see related post here https://stackoverflow.com/a/10566463/4904726
so try this way
alter table matches add foreign key (project_id, project_name) references projects(project_id, project_name);
Do you understand what a FK constraint says? It says a list of values for some columns in a table must appear as a list of values for some columns forming a (declared) PK or UNIQUE NOT NULL in the referenced table. So what you are writing doesn't make sense. If you wanted a PK (project_id, project_name) then that should also be the form of your FK.
But (project_id, project_name) is not two 1-column PKs, it is one 2-column PK, and it is probably not what you want since presumably in projects it isn't just pairs that are unique it is each column. Presumably you want two 1-column PKs and two one-column FKs, one referencing each PK.
If projects project_id was NOT NULL you could write:
alter table projects add primary key(project_name);
alter table matches add column project_name varchar(30),
add foreign key (project_name) references projects(project_name);
But if project_name can be NULL in projects then you cannot make it a PK and you cannot sensibly have a FK to it. You can make it UNIQUE. Unfortunately MySQL lets you write such a FK declaration to a non-NULL UNIQUE column while it also tells you not to do it:
The handling of foreign key references to non-unique keys or keys that contain NULL values is not well defined for operations such as UPDATE or DELETE CASCADE. You are advised to use foreign keys that reference only keys that are both UNIQUE (or PRIMARY) and NOT NULL.
So if you want projects project_name to be nullable then should declare it UNIQUE but you should enforce the logical matches project_name match with a trigger.
I have this kind problem regarding sql:
Table 1: ID_1 (Primary Key) | NAME | LASTNAME | EMAIL...
Table 2: ID_2 (Primary Key) | NAME2 | LASTNAME2 | EMAIL...
Normally using constraints it is possible to make as column in TABLE 2
(NAME 2 for example) as a foreign key for NAME the first TABLE 1.
The general relation would be one-many. That's one value from column NAME in TABLE 1 used many times in column NAME2 in Table 2.
Now what I want to achieve is that making the rule one-to-one, so I cannot have duplicated values of NAME from table TABLE 1 in TABLE 2.
Does it require triggers or it can be set by constraint when creating the tables?
Steps to achieve this:
Create foreign key constraint
Create unique constraint
This can all be done while creating the table.
CREATE TABLE table2 (
...,
name2 varchar(255),
FOREIGN KEY (name2) REFERENCES table1(name),
UNIQUE (name2)
);
If you already have the table, use ALTER TABLE instead.
When trying to insert a row with value of name2 that is already in a table, an error will be raised.
Yes it can be set by constraint. You can have foreign keys and unique keys on the same field. The unique constraint will guarantee there is only one record with one reference to the primary table (from that foreign table)
I've run this query on mysql:
ALTER TABLE `connections`
ADD CONSTRAINT `connections_serial_fk`
FOREIGN KEY (`serial`)
REFERENCES `devices`(serial)
ON DELETE CASCADE;
And I'm getting error number 150. I already looked for the documentation and the thing I think that may be causing this error is that the column 'serial' is a varchar(255).
This reference says "innodb permits a foreign key to reference any index column or group of columns".
Does MySql have this restriction?
From my schema:
devices:
| Field | Type | Null | Key | Default | Extra |
| serial | varchar(255) | YES | | NULL | |
connections:
| Field | Type | Null | Key | Default | Extra |
| serial | varchar(255) | YES | | NULL | |
A dbms that conforms to standard SQL will prevent you from setting a foreign key reference to a column (or columns) that doesn't have some kind of unique constraint on it--either PRIMARY KEY or UNIQUE. But MySQL does permit this kind of nonsense under certain circumstances.
Additionally, MySQL requires that the referenced columns be indexed
for performance reasons. However, the system does not enforce a
requirement that the referenced columns be UNIQUE or be declared NOT
NULL. The handling of foreign key references to nonunique keys or keys
that contain NULL values is not well defined for operations such as
UPDATE or DELETE CASCADE. You are advised to use foreign keys that
reference only UNIQUE (including PRIMARY) and NOT NULL keys.
Foreign keys should reference only a column (or columns) that have been declared either PRIMARY KEY or NOT NULL UNIQUE. If you think you need a foreign key reference to a nonunique column or columns, that's a big red flag, waving in your face, held by a guy yelling, "You have a design problem!"
Well, i have two tables
publica_evento_grupo
Field | Type | Null | Key | Default | Extra
id_evento_grupo int(10) unsigned NO PRI auto_increment
id_evento int(8) unsigned NO MUL
id_grupo int(8) unsigned NO MUL
identificacao varchar(55) NO
publica_identificacao_publicacao
Field | Type | Null | Key | Default | Extra
id_evento int(8) unsigned NO PRI
identificacao varchar(55) NO PRI
publica_evento_grupo.id_evento in is a foreign key to a third table called publica_evento but is also a foreign key together with the column to the table publica_identificacao_publicacao.identificacao. The problem is, I got to create the foreign key that relates publica_evento_grupo to publica_identificacao_publicacao by the key id_evento, but when I try to create the another FK with the column identificacao, it gives the errno below
[Err] 1005 - Can't create table '#sql-1049_1980992' (errno: 150).
As you can see the table publica_identificacao_publicacao has two PK and that iss the reason that it has to be 2 FK to relate them, i didn't create the indexes yet, because as far as i know, i just have to create the indexes after adding the FK contraints, and I was able to create the FK contraint to the column id_evento between evento_grupo and identificacao_publicacao, i don't know why just the column identificacao is giving this error
EDIT 1: #RolandBouman i don't have the permission to use that command SHOW ENGINE INNODB STATUS
EDIT 2: #Geoff_Montee acctually the command you passed worked, to undestand why i use that structure take a look at this question MySQL UNIQUE Constraint multiple columns condition
Without the actuall DDL it's not so easy to say. I recommend doing:
SHOW ENGINE INNODB STATUS;
Immediately after you run into this error. In the output, look for a section that looks like:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
121026 22:40:18 Error in foreign key constraint of table test/#sql-154c_94:
foreign key(rid) references bla(id):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
You'll find detailed info there about what's wrong with your foreign key definition.
That error usually happens because there is a type mismatch between the referring table and the referred table. In this case, the types seem to match.
Have you considered having a constraint for both fields in the primary composite key? You might have to remove the existing foreign key constraint on id_evento first.
ALTER TABLE publica_evento_grupo ADD FOREIGN KEY
(id_evento, identificacao) REFERENCES
publica_identificacao_publicacao (id_evento, identificacao);
It seems as though the error in this case might be because you try to add a foreign key constraint to only part of a composite primary key.
Does identificacao exist in any other tables? Why do you want to add a foreign key constraint to only part of a composite primary key?
Think about it this way...
Let's say you do have a foreign key constraint in the publica_evento_grupo table to the identificacao field by itself. Let's also say in the publica_identificacao_publicacao table you have (1, "some string") and (2, "some string"). So if you delete (2, "some string"), but leave (1, "some string") in its place. The rows that refer to (1, "some string") in the publica_evento_grupo table will complain, even though they shouldn't!
So it sounds to me like you should add a foreign key constraint to all of a primary key or none of it.
I'm going to be honest, I'm a bit hazy on how primary and foreign keys work. I was told to setup my database by someone on here so that I had 7 tables, one for organizations, one for categories, services, and cultures, and three cross reference tables between organization on one hand, and categories, services and cultures on the other.
Take the org_culture_xref table, for instance. I have two columns, one is org_id, which is the same as the org_id column (primary key) of the organization table. The other is cult_id, which is the same as the cult_id column (primary key) of the culture table.
I believe both of the columns of the org_culture_xref table are primary and foreign keys. However, this doesn't seem to allow me to have multiple values for both of these columns. I want to be able to have several relationships between organizations and cultures - as in every organization can be associated with multiple cultures and every culture can be associated with multiple organizations.
How do I ensure that I can have multiple values for both columns?
What you're talking about is a Many-To-Many relationship. You're on the right path using a cross-reference table.
It's good to review how foreign and primary keys work; there can only be one primary key per table, but there can be multiple foreign keys. However, note that a primary key doesn't have to be limited to one column; you can have a primary key that spans two, three, or more columns.
Your solution here is to have two foreign key, one for each column/table relationship, and one primary key that spans across both tables.
Here's an example of a table I used at one time, which links cities and counties in a many-to-many relationship.
mysql> show create table xref_cities_counties\G
*************************** 1. row ***************************
Table: xref_cities_counties
Create Table: CREATE TABLE `xref_cities_counties` (
`city_id` int(10) unsigned NOT NULL,
`county_id` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`city_id`,`county_id`),
KEY `city_id` (`city_id`),
KEY `county_id` (`county_id`),
CONSTRAINT `fk_xrefcitiescounties_cityid` FOREIGN KEY (`city_id`) REFERENCES `florida_cities` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_xrefcitiescounties_countyid` FOREIGN KEY (`county_id`) REFERENCES `florida_counties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql>
mysql>
mysql> describe xref_cities_counties;
+-----------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+-------+
| city_id | int(10) unsigned | NO | PRI | | |
| county_id | tinyint(3) unsigned | NO | PRI | | |
+-----------+---------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql>
I'd suggest some extra reading on the topic. It seems like you're on a good start.
The primary key for your cross ref table will be both of the columns, meaning that the combination of two ids must be unique but you can have repeats of individiual ids in either column.
Here is a statement to create such a table:
CREATE TABLE `x` (
`a_id` varchar(6) NOT NULL default '',
`b_id` varchar(6) NOT NULL default '',
PRIMARY KEY (`a_id`,`b_id`)
)
The issue itself and the cross ref table approach to many-to-many relationships applies to most (if not all) relational databases, but since I haven't used mysql in around 10 years I got that code from here, which seems to have a detailed discussion of the topic with mysql specific code.
Each column of org_culture_xref is a foreign key: org_id is a foreign key to organization, and cult_id is a foreign key to culture. The two of them together are the primary key of org_culture_xref.
So, something along these lines:
CREATE TABLE org_culture_xref
(
org_id NUMERIC(10) NOT NULL,
cult_id NUMERIC(10) NOT NULL,
PRIMARY KEY (org_id, cult_id),
FOREIGN KEY (org_id) REFERENCES organization (org_id),
FOREIGN KEY (cult_id) REFERENCES culture (cult_id)
);