Add column on table with value dependent on foreign key - mysql

I'm not sure if there is already an answer for this but I didn't manage to find anything.
I have a table named Offer with a primary key ID and another column let's say Mask.
Offer -->
ID Mask
1 0
2 1
3 0
Let's say I have a completely different table Production that has a column-foreign key Offer_ID that references to the ID of table Offer.
I want to add a column Mask that will obtain the Mask value of the Offer row that the foreign key references to.
For example:
Production-->
ColA ColB Offer_ID Mask
.. .. 1 Here I want 0
EDIT:
The table Offers exists and so do its columns ID and Mask.Table Productions also exists,so does the column Offer_ID and is a foreign key to ID of tables Offers.I want to add a column Mask and set its values according to the Offer_ID column value.
The point is I don't want just to set the values properly,but I want whenever a new row is inserted to Productions the Mask column to get a value same with that of the row that foreign key(Offer_ID) references to.

You could join the two tables:
SELECT p.cola, p.colb, p.offer_id, o.mask
FROM production p
JOIN offer o ON p.offer_id = o.id

Related

Store dynamic number of entries in one table to a single row in another table

I have a table called users with the following columns:
| id | name |
Then another table called images which looks like this:
| id | fileName |
What is the best way to assign a dynamic number of image rows to a to multiple user rows.
You need to add a foreign key to your images table. For example, change your images table to have three columns:
| id | fileName | userID |
This userID must be one of the id values that already exists in the users table, otherwise this column would be pointless. This column will point back to the users table and essentially assigns each image to a specific user. Since one user can have many paintings, we call this a one-to-many relationship.
If you already have the tables created, you can try and run the following query:
ALTER TABLE images ADD userID INT NOT NULL DEFAULT 0;
ALTER TABLE images ADD CONSTRAINT fk_user FOREIGN KEY (userID) REFERENCES users(id);
The first line will add the column, while the second line makes the constraint for it. The constraint ensures that new rows added to the images table MUST have a valid userID. If you try and add a row with a userID that does not exist, you will get an error (and rightfully so, because images shouldn't belong to imaginary users).
This will also set the userID column of all existing image rows to 0. You may want to change this later, but that depends on your individual case.

How to delete a certain row from mysql table with same column values?

I have a problem with my queries in MySQL. My table has 4 columns and it looks something like this:
id_users id_product quantity date
1 2 1 2013
1 2 1 2013
2 2 1 2013
1 3 1 2013
id_users and id_product are foreign keys from different tables.
What I want is to delete just one row:
1 2 1 2013
Which appears twice, so I just want to delete it.
I've tried this query:
delete from orders where id_users = 1 and id_product = 2
But it will delete both of them (since they are duplicated). Any hints on solving this problem?
Add a limit to the delete query
delete from orders
where id_users = 1 and id_product = 2
limit 1
All tables should have a primary key (consisting of a single or multiple columns), duplicate rows doesn't make sense in a relational database. You can limit the number of delete rows using LIMIT though:
DELETE FROM orders WHERE id_users = 1 AND id_product = 2 LIMIT 1
But that just solves your current issue, you should definitely work on the bigger issue by defining primary keys.
You need to specify the number of rows which should be deleted. In your case (and I assume that you only want to keep one) this can be done like this:
DELETE FROM your_table WHERE id_users=1 AND id_product=2
LIMIT (SELECT COUNT(*)-1 FROM your_table WHERE id_users=1 AND id_product=2)
Best way to design table is add one temporary row as auto increment and keep as primary key. So we can avoid such above issues.
There are already answers for Deleting row by LIMIT. Ideally you should have primary key in your table. But if there is not.
I will give other ways:
By creating Unique index
I see id_users and id_product should be unique in your example.
ALTER IGNORE TABLE orders ADD UNIQUE INDEX unique_columns_index (id_users, id_product)
These will delete duplicate rows with same data.
But if you still get an error, even if you use IGNORE clause, try this:
ALTER TABLE orders ENGINE MyISAM;
ALTER IGNORE TABLE orders ADD UNIQUE INDEX unique_columns_index (id_users, id_product)
ALTER TABLE orders ENGINE InnoDB;
By creating table again
If there are multiple rows who have duplicate values, then you can also recreate table
RENAME TABLE `orders` TO `orders2`;
CREATE TABLE `orders`
SELECT * FROM `orders2` GROUP BY id_users, id_product;
You must add an id that auto-increment for each row, after that you can delet the row by its id.
so your table will have an unique id for each row and the id_user, id_product ecc...

Add a Foreign Key to an Existing Table that Contains what would be Invalid FK Values (MYSQL)

I need to add a Foreign Key to a table that already exists and is populated with data that would contain invalid Foreign Key Values. (MYSQL)
I know there are several questions along these lines, but I can't seem to find any that answer my scenario.
Table and Data Structure
"GblTable" contains an "Org" field that needs to become a FK of the Org table. The Org table has a PK field called "number".
Currently, the GblTable contains non-existent Org numbers (ie. If the Org table has rows with PKs 1,2, and 3, GblTable might have rows with Org as 4 or 5). While this is the case, I cannot apply the constraint to reference GblTable.org to Org.number.
I believe the best approach for this particular situation will will be to set the FK field in those rows to NULL before I apply the constraint. NULL is a valid GblTable.Org value for the program, so this would achieve an acceptable outcome.
What I Have so Far
I want to set all GblTable.Org values to NULL where they do not match a valid Org.Number.
In pseudocode:
set GblTable.ORG to NULL
where the GblTable.number is one of the following:
( select all GblTable.numbers where the GblTable.Org does not match an existing Org.Number )
In Sql, but I get the error "You can't specify target table 'GblTable' for update in FROM clause":
update GblTable set Org=NULL
where number IN (
select number
from GblTable
where Org NOT IN (select number from Org)
)
What's the best way to achieve my requirement?
You don't need the extra level of subquery:
update GblTable set Org=NULL
where Org NOT IN (select number from Org)

How to set a database integrity check on foreign keys referenced fields

I have four Database Tables like these:
Book
ID_Book |ID_Company|Description
BookExtension
ID_BookExtension | ID_Book| ID_Discount
Discount
ID_Discount | Description | ID_Company
Company
ID_Company | Description
Any BookExtension record via foreign keys points indirectly to two different ID_Company fields:
BookExtension.ID_Book references a Book record that contains a Book.ID_Company
BookExtension.ID_Discount references a Discount record that contains a Discount.ID_Company
Is it possible to enforce in Sql Server that any new record in BookExtension must have Book.ID_Company = Discount.ID_Company ?
In a nutshell I want that the following Query must return 0 record!
SELECT count(*) from BookExtension
INNER JOIN Book ON BookExstension.ID_Book = Book.ID_Book
INNER JOIN Discount ON BookExstension.ID_Discount = Discount.ID_Discount
WHERE Book.ID_Company <> Discount.ID_Company
or, in plain English:
I don't want that a BookExtension record references a Book record of a Company and a Discount record of another different Company!
Unless I've misunderstood your intent, the general form of the SQL statement you'd use is
ALTER TABLE FooExtension
ADD CONSTRAINT your-constraint-name
CHECK (ID_Foo = ID_Bar);
That assumes existing data already conforms to the new constraint. If existing data doesn't conform, you can either fix the data (assuming it needs fixing), or you can limit the scope (probably) of the new constraint by also checking the value of ID_FooExtension. (Assuming you can identify "new" rows by the value of ID_FooExtension.)
Later . . .
Thanks, I did indeed misunderstand your situation.
As far as I know, you can't enforce that constraint the way you want to in SQL Server, because it doesn't allow SELECT queries within a CHECK constraint. (I might be wrong about that in SQL Server 2008.) A common workaround is to wrap a SELECT query in a function, and call the function, but that's not reliable according to what I've learned.
You can do this, though.
Create a UNIQUE constraint on Book
(ID_Book, ID_Company). Part of it will look like UNIQUE (ID_Book, ID_Company).
Create a UNIQUE constraint on Discount (ID_Discount, ID_Company).
Add two columns to
BookExtension--Book_ID_Company and
Discount_ID_Company.
Populate those new columns.
Change the foreign key constraints
in BookExtension. You want
BookExtension (ID_Book,
Book_ID_Company) to reference
Book (ID_Book, ID_Company). Similar change for the foreign key
referencing Discount.
Now you can add a check constraint to guarantee that BookExtension.Book_ID_Company is the same as BookExtension.Discount_ID_Company.
I'm not sure how [in]efficient this would be but you could also use an indexed view to achieve this. It needs a helper table with 2 rows as CTEs and UNION are not allowed in indexed views.
CREATE TABLE dbo.TwoNums
(
Num int primary key
)
INSERT INTO TwoNums SELECT 1 UNION ALL SELECT 2
Then the view definition
CREATE VIEW dbo.ConstraintView
WITH SCHEMABINDING
AS
SELECT 1 AS Col FROM dbo.BookExtension
INNER JOIN dbo.Book ON dbo.BookExtension.ID_Book = Book.ID_Book
INNER JOIN dbo.Discount ON dbo.BookExtension.ID_Discount = Discount.ID_Discount
INNER JOIN dbo.TwoNums ON Num = Num
WHERE dbo.Book.ID_Company <> dbo.Discount.ID_Company
And a unique index on the View
CREATE UNIQUE CLUSTERED INDEX [uix] ON [dbo].[ConstraintView]([Col] ASC)

Refactor Foreign Keys with Update after Primary Key change

We ran into a problem with out primary key. It was set to a meaningful value for ease of data entry since all data was originally added directly. However now the meaningful value is not always present in all entries. So now we are moving to an auto-generated, non-meaningful key. But I have to update the database to reflect this.
So my products table has the columns serial (the original key) and Id (the new PK). My parts table has the 2 columns FK_serial (the old FK) and FK_product (the new FK, currently set to 0 for all entries).
Is there a UPDATE statement that will walk through the parts table and set the FK_product to the value of Id in the products table where serial = FK_serial?
UPDATE parts
JOIN products
ON parts.FK_serial = products.serial
SET parts.FK_product = products.Id;