I have 2 tables: let say table 1 (userid, username, password) and table 2 (userid, a, b, c).
table 1 has a userid field (primary key), table 2 also has userid (references table 1).
If I do an insert statement, to add a row to table 2, how does table 2 generate the userid field?
Edit:
I want to insert things into table 2 where the userid in table 2 MUST match userid in table 1 - what constraints do I need to set up
The database doesn't understand the relationship between table1 and table2 unless you explicitly specify it. You can use SQL foreign keys if you are using a database engine the supports them (InnoDB).
CREATE TABLE table1 (
userid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL);
CREATE TABLE table2 (
rowid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
userid INTEGER NOT NULL
REFERENCES table1(userid)
ON DELETE CASCADE ON UPDATE CASCADE
-- other columns here
);
The REFERENCES option will tell the database engine that table2.userid requires that a row exist in table1 such that table1.userid = table2.userid. The ON DELETE and ON UPDATE clauses will cause the deletion of a row in table1 to automatically delete/update rows in table2.
You cannot create a row in table2 until you have created a row for the user in table1. The row in table1 will auto-generate the userid. When you insert into table2, you will explicitly include the user id from table1 to establish the linkage between the rows.
If the userid field on table2 is not autoincrement then you have to provide the value or the insert will fail.
If you have defined userID in table2 as foriegn key constraint, then you will need to have the corresponding userID in the table1 as reference when inserting rows to table2, else if you have not defined any such constraints, then it will not matter.
Keep in mind, if the constraint is defined, then table2 will not generate ID by itself. It would require the ID to be present in the table1 column which is referenced.
If username and password is not null then don't insert in tabel 1 and give error
Related
I currently have 3 fields in a table:
id, client_id, username
The client_id and username combination should never be duplicates. The original thought was to use a composite primary key for client_id and username. This however did not allow my "ID" field to auto increment as it was not primary.
If I were to add my ID to my composite, there would never be a duplicate as the ID is always changing.
The latest I have is a basic:
"INSERT IGNORE INTO users (client_id, username) VALUES(cid,username)"
Is there a way to check that client_id and username are a match for any previous records, and if they are, then don't add them? The above does not work.
ALTER TABLE yourTable
ADD CONSTRAINT constraint_name UNIQUE ( client_id ,username);
you can add a unique key by combination of client_id ,username in your table .
You can create the table like this so that client_id and username will'nt get matched for any previous records...
CREATE TABLE table1 (
id int,
client_id int,
username varchar(255),
PRIMARY KEY('id','client_id')
);
I have the following problem:
Every author has a name and n-aliases for this name. Every alias comes from a source. Every alias has m sources. For example
AUTHOR| ALIAS | SOURCE
-------------------------
Will| Willy |George
Will| Bill | Jenny
William| Will| Francis
William| Bill| Maya
I have one table for the author and his name, one for all of his aliases:
CREATE TABLE alias (
authors_id INT NOT NULL,
alias VARCHAR(150) NOT NULL,
id INT NOT NULL AUTO_INCREMENT
PRIMARY KEY (author_id,alias);
id serves as foreign key.
Here's the second table for the sources
CREATE TABLE alias_source (
id INT NOT NULL AUTO_INCREMENT
source VARCHAR(150) NOT NULL,
alias_id INT NOT NULL,
PRIMARY KEY (id)
FOREIGN KEY (alias_id) REFERENCES alias(id);
Now I need an MySQL insert statement for when I insert
author,alias,source into alias that the source is inserted into alias_source.
And on duplicate alias no only a new source is added.
An INSERT statement in SQL can only insert into one table, and can only list columns of that one table. You can't include your source column in the INSERT statement, because it's not a column of the alias table.
Triggers can allow you to insert into a secondary table, but the trigger needs to know the value to insert. In this case the trigger doesn't have any way of getting the value for source.
This is a task that is much easier to do with two INSERT statements.
INSERT IGNORE INTO alias SET author_id = ?, alias = ?;
INSERT INTO alias_source ...
But you have a problem because your alias table has an auto-increment column id, but this column is not part of a key. In InnoDB, you must make the auto-increment column the first column of a key.
Your alias_source table has a foreign key referencing alias(id) but that's not allowed. A foreign key must reference a key of the parent table. It should reference the unique or primary key, and should reference all columns of the key (otherwise you get a row in a child table that might reference multiple rows in the parent table, and that makes no sense).
If you want to use an auto-increment column for your alias table, make it the primary key, and put a secondary UNIQUE constraint on the other columns.
CREATE TABLE alias (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
authors_id INT NOT NULL,
alias VARCHAR(150) NOT NULL,
UNIQUE KEY (author_id,alias));
Then query the id after you insert. Whether you inserted a new row, or the row already existed, you'll get the id for the row with the chosen author and alias.
INSERT IGNORE INTO alias SET author_id = ?, alias = ?;
SELECT id FROM alias WHERE author_id = ? AND alias = ? INTO #id;
INSERT INTO alias_source SET alias_id = #id, source = ?;
Re your followup question in comment:
Good idea, but it doesn't work the way you may think it does. You can do a dummy set of id=id and set a session variable as a side effect.
mysql> insert into alias set author_id=1, alias='alias'
on duplicate key update id = #id:=id;
mysql> select #id;
+------+
| #id |
+------+
| NULL |
+------+
But why didn't it set the session variable to the id? Because this insert was not a duplicate, it was a new row. So the id value had not yet been generated by auto-increment at the time the IODKU executed.
If you subsequently do the same IODKU for a row that is a duplicate, the id value has previously been added to the row, so you get the value in the side-effect:
mysql> insert into alias set author_id=1, alias='alias'
on duplicate key update id = #id:=id;
mysql> select #id;
+------+
| #id |
+------+
| 1 |
+------+
So you'd have to write application code anyway to check if #id is NULL or not, and do a SELECT id query if #id is NULL.
That seems more complicated than just doing the SELECT id as a standard action following the INSERT IGNORE like I showed above.
I have created two tables and they have a simple fk relationship. The tables are like below:
table_1
field_1 (primary key)
table_3
field_1 (fk on table_1)
field_2 (fk on table_2)
and then I have created the FK with the line below:
ALTER TABLE `table_2`
ADD CONSTRAINT `fk_table_2`
FOREIGN KEY (field_1`) REFERENCES `table_1` (`field_1`);
What I expect is that, if I try to delete a record in my table_1 where field_1 = x and another record with the same x value is present in table_2 as field_1, I should get an error.
Actually, I don't get any error and the record is removed from table_1 leaving an orphan child record in table_2.
I don't use the delete cascade because I want avoid this.
Why I don't get any error?
I have a query which updates the table or inserts if the row does not already exist, but for some reason it just inserts all the time.
This is my table structure:
Id (primary) | uid | product_id | quantity
This is my query:
INSERT INTO my_table (uid,product_id,quantity)
SELECT t1.uid,?,?
FROM checker t1
WHERE t1.id = ?
ON DUPLICATE KEY UPDATE
product_id = ?, quantity = quantity+?
What i want to do though is use on duplicate key if uid + product_id combination exist in the table already.
So is there a way to designate what kind of duplication to look for to update instead of insert?
There is no way to distinguish between what duplication occurs.
As soon as any unique constraint is violated - it will perform ON DUPLICATE KEY UPDATE part.
For your case you just need to create unique composite key that consists of 2 fields: (uid, product_id)
I'm a total newbie and I'm trying to do a mysql database, using xampp for linux 1.8.1.
I want to make a relation between two tables A and B. For what I know foreign keys create a bijection, or a one-to-one relation. I must not have such a strict relation, so I only created a column inside table A that stores the id of table B.
Is this correct? There's not a way to enforce it? I mean, this way you could delete a row of table B that is referenced in table A. you could store a value inside A that doesn't correspond to an id of any row of B. How to prevent this?
The main problem for me is to prevent deletion of a row of table B if the row id is referenced by a row of table A.
create table table_b (
b_id integer primary key
);
create table table_a (
b_id integer primary key references table_b (b_id)
);
insert into table_b values (1);
insert into table_a values (1);
The following statement will fail.
delete from table_b where b_id = 1;
If you'd built that with PostgreSQL, the error message would say
ERROR: update or delete on table "table_b" violates foreign key constraint "table_a_b_id_fkey" on table "table_a" Detail: Key (b_id)=(1) is still referenced from table "table_a".
That structure gives you a "1 to 0 or 1" relationship between the two tables. For "1 to 0 or many", add one or more columns to table_a's primary key.
create table table_b (
b_id integer primary key
);
create table table_a (
b_id integer references table_b (b_id),
checkout_date date not null default current_date,
primary key (b_id, checkout_date)
);
That structure will let table_a store multiple rows for one value of b_id, but each of those rows must have a different checkout_date.
I think you allways need an primarykey for this, or you write a trigger who checks the consistence of ID from B when a change occurs.
I dont know that it would be possible without a trigger or a constraint ...