simple update of foreign key in php mysql website - php

hi i cannot update a table which has foreign keys on it. in this table, instead of displaying the primary keys of the foreign key, i choose to display their names: this is a simple diagram:
Here are my foreign tables:
Size Table:
sId sName
1 1x1
2 2x2
Brand Table:
bId bName
1 brand1
2 brand2
Supplier Table:
sId sName
1 supp1
2 supp2
So here is my Warehouse Table using a join statement:
pId pName pSize pBrand pSupplier
1 prod1 1x1 brand1 supp1
2 prod2 2x2 brand2 supp2
here is my edit in php and mysql form:
########### EDIT PRODUCT
if(isset($_POST['editproduct'])){
$product_id=$_POST["product_code"];
$product_name=$_POST["product_name"];
$size_name=$_POST["size_name"];
$brand_name=$_POST["brand_name"];
$supplier_name=$_POST["supplier_name"];
$sql = "UPDATE warehouse SET
product_name='$product_name'
,size_id='$size_id'
,brand_id='$brand_id'
,supplier_id='$supplier_id'
WHERE
product_code='$product_code'";
$result=mysql_query($sql,$connection) or die(mysql_error());
header("location: warehouse.php");
} ?>
the weird thing is that the first try i edit the table it does not error. but for the second time, it prompts me the error of foreign key constraint, :(
i have a feeling that because i use a join statement in my warehouse table, that conflicts my update query since the one i am updating is the primary key and i only display its name.

you reference the variables $size_id, $brand_id, $supplier_id in your SQL statement but never set them anywhere..
Though if you say that the edit works the first time, I'm guessing you might not have posted all your code?

Related

SQL ID value auto move up

I have a table which an auto-increment ID column. I want my database to automatically change the ID value so there is always an ID value of 1.
For example:
ID Firstname Lastname
1 John Smith
2 Charlie Jacobs
3 Jason young
I want it so that if I delete row ID 1 then row ID 2 changes to ID 1 and row ID 3 changes to ID 2. Like this:
ID Firstname Lastname
1 Charlie Jacobs
2 Jason young
I want to be able to then add names after which would carry on from ID 3. Preferably I was wondering if there was a setting in SQL that can do this automatically. If this isn't possible then a PHP script would be the second best thing.
That is not a right thing to do. Why do you want to do that? This would mess up your primary key values. So don't do it. Coming to the solution
If you are displaying this inside a form, just generate a row number for each row in your select statement. It will not have any gaps in between. MYSQL Generating Row Numbers
SELECT #row_number:=#row_number+1 AS row_number,db_names FROM mysql_testing,
(SELECT #row_number:=0) AS t
ORDER BY db_names;

Check if an id exists in a table before adding it to another table

I'm doing a small thing like the like feature you see on facebook. So the way I'm doing it is like this. I have a table called products which contains products that people can like.
Like this (stripped down):
id | prodName | status (0=clear, 1=blocked)
----------------------------------------------------------
1 | Philips Food Processor | 0
2 | Le Sharp Knife | 0
3 | Ye Cool Fridge | 0
Then comes the `likes` table like this:
id | prodName | prodId | userId
--------------------------------------------
1 | Philips Food Processor | 1 | 1
2 | Le Sharp Knife | 2 | 1
3 | Ye Cool Fridge | 3 | 1
4 | Ye Cool Fridge | 3 | 2
I need to check, before adding to the likes table, if a product with that id actually actually exists in the products table and its status = 0. I currently do this with a lot of php code. What would be a good way to do this using sql? Is it possible? Using foreign keys or something like that?
I'm using innodb table type.
You can do a conditional insert. For product 6 and user 7:
insert into Likes
(prodName, prodId, userId)
select prodName
, id
, 7
from Products
where id = 6
and status = 0
If this inserts no rows, you know that the product did not exist with status 0.
If you just want to phrase the insert so it follows the rules, then you can use insert . . . select as follows:
insert into likes(prodId, userId)
select <prodid>, <userid>
from products p
where p.prodid = <prodid> and status = 0
I don't think MySQL supports "partial" foreign key constraints, where you can also include the requirement on the flag.
And, you shouldn't put the product name int he likes table. You should look it up in the products table.
The key element of trying to add something to the likes table that does not exist in the product table is the feedback to the user that lets them know they're doing it wrong. Any answer you determine on should not ignore the user feedback side of things - which is basically going to require your PHP code.
However, yes - there is a way to do it via foreign keys. You can index the prodid in the second table, and reference it as a foreign key to the first table.id. This means that if you try an insert and you get an error, there's a chance that the problem is that you're trying to add something without a match in the first table.
However, trying to determine precisely what the error is so you can determine the proper logic to respond to that error causes its own mass of php code, and is less easily transparent for future developers to maintain. I'd suggest a simple method in your Product object: isValid( id ) that returns true/false - so your 'check for this' code simply goes if( Product.isValid( prodId ) ){ Like.insert( userId, prodId ); }
But at the same time, I'd REALLY recommend a foreign key constraint along with the php code you're probably already using, just as insurance against your database becoming cluttered with unlinked rows. It's usually best to have multiple barriers against bad data.
Additionally ... is there a reason why you're storing the product names both in the product table AND in the likes table? I don't see why you'd need it in the likes table.
--Check to see if cleared product exist in products table
Select count(*) from products p where p.status = 0 and p.id = %IDVALUE
--Check if your user previous liked product
Select count(*) from products p, likes l where p.id = l.prodId and l.userId = %USERID
In your code you can execute the statements (replace %IDVALUE and %USERID with actual values) and check the return column to get the count and preform your custom logic.
Currently you require the prodId to populate the likes table, hence you need to lookup the data regardless of the contraint regarding blocked. Hence:
INSERT INTO likes (prodname, prodId, userId)
SELECT prodname, id, 123456
FROM products
WHERE prodname='Le Sharp Knife'
AND status=0;
(just substitute 123456 and 'Le Sharp Knife' for the parameters you need).
Yuo need to query database to check record,
for example you product id is 2 so your query would be something like
$query = select * from 'your-like-table' where 'prodId ' = 'ID';
then
if ( !mysql_query('your-db',$query)):
if you come under this condition then it's the time when you enter your like to database
endif;
hope it helps

MySQL database design for image options relationships

I have two tables, images and image_data and here is an example of my image_data table.
image_id | slide_id | language_id | type |
101 | 1 | 1 | CQ |
101 | 2 | NULL | NULL |
56 | 5 | 1 | TN |
56 | NULL | 2 | NULL |
So basically, each image will have different options and I am wondering the best way to implement this.. because I have a feeling I am doing this the wrong way.
With this, I can run a query to use GROUP_CONCAT() to turn values in multiple rows into a single concatenated string.
image_id | slide_id | language_id | type |
101 | 1,2 | 1 | CQ |
56 | 5 | 1,2 | TN |
Which is fine, but the problem with the way I am doing it right now is..it seems like it will be really difficult to update the rows with my backend system.
So with my query, I can determine which ones to check based on the database since I have it all in one row since I concatenated it. But now it's like.. when I go to click "Save" and update the rows, which one do I update? there can be more than 1 row of the same image id, so how would I update the right one, and so on.
If I checked off another slide for image #101 then I would need to create a new row for it. If after that I wanted to add another language_id to it, then I would need to make sure to not add a new row since one exists with a NULL value, and to just replace the NULL value with the new language id.
It just seems really complicated and there's so many factors, that using this method is really hard to program.
What would be the best way to do this? Any suggestions are really appreciated.
Thanks!
What you need to do is implement N:M (many-to-many) relationships between your images and slides / languages / types tables so that your design is more normalized (one fact in one place).
Think of it this way: one image can have multiple slides, and one slide may be an option of multiple images. -- this is a N:M relationship. Same goes for languages and types.
What you need to do is get rid of your image_data table which houses the options between ALL entities and have three separate cross-reference tables instead. Here's how you would model it:
Base tables:
images(image_id [PK], ...)
slides(slide_id [PK], slide_name, ...)
languages(language_id [PK], language_name, ...)
types(type_name [PK], ...)
Cross-Reference tables:
images_has_slides(image_id [PK], slide_id [PK])
images_has_languages(image_id [PK], language_id [PK])
images_has_types(image_id [PK], type_name [PK])
How it would look in ER:
With this type of design, you wouldn't have to deal with NULL values or figuring out which row to update because you now have just one fact in one place. To get all options, you would still have to do GROUP_CONCAT() like so:
SELECT
a.*,
GROUP_CONCAT(c.slide_name) AS slides,
GROUP_CONCAT(e.language_name) AS languages,
GROUP_CONCAT(f.type_name) AS types
FROM
images a
LEFT JOIN
images_has_slides b ON a.image_id = b.image_id
LEFT JOIN
slides c ON b.slide_id = c.slide_id
LEFT JOIN
images_has_languages d ON a.image_id = d.image_id
LEFT JOIN
languages e ON d.language_id = e.language_id
LEFT JOIN
images_has_types f ON a.image_id = f.image_id
GROUP BY
a.image_id
Then to update image options, you would use INSERT and DELETE on the cross-reference tables:
Let's say you wanted to add two languages to an image, you would do
INSERT INTO images_has_languages (image_id, language_id)
VALUES (101, 4), (101, 5);
The above query adds languages with id's of 4 and 5 to the image that has an id of 101.
To remove options (unchecking on the form) - let's say you wanted to remove 2 slides from an image
DELETE FROM images_has_slides WHERE image_id = 101 AND slide_id IN (3,6)
This removes slides with id's of 3 and 6 from the image that has an id of 101.
So in your application, you could figure out if you need to do insert/delete queries based on if the user unchecked or checked values in the form for the image.
Have you tried splitting the tables? If you make a separate table for the slide and language and kept the type in the same table as the image ID you could then use that to make your lists. You could then optimize your database with foreign keys so you don't take as big a performance hit.
Here what I mean:
Image data table: two columns, image_id and image_type (type is a reserved word). Imageid is the primary key so there are no duplicates (assuming you only want one type for each image)
Image-language table: two columns, image id and image_language. Both are primary keys so you don't duplicate languages on the same image id, but an image id can have multiple languages. Primary key from image id links to the primary key in the image data table
Image-slide table: two columns, image id and slide number. Same as above (two primary keys, relationship, etc)
This way you could get get all the data like so:
SELECT d.image_id, d.image_type, l.image_language, s.slide_number FROM image_data d LEFT JOIN image_language l ON d.image_id = l.image_id LEFT JOIN image_slide s ON s.image_id = s.image_id
The left joins make sure all the item id always shows up no matter what even if there isn't enough languages or slides to go around. It will create a "matrix" of sorts for you with a row for each image and each language and each slide it applies to. For example, if you had an image that had spanish and english as its language and 4 slides, you would get 8 entries: one for each slide in each language.
I don't know if that will necessarily solve the problem, but it would make it a little easier to control exactly what is in the database while still having the database do a bit of the work for you.
You need to normalize your schema.
You have images table:
CREATE TABLE images (
image_id integer,
image_name varchar(100),
PRIMARY KEY(image_id)
);
Each image can have several slides:
CREATE TABLE slides (
slide_id integer,
image_id integer,
slide_name varchar(100),
PRIMARY KEY(slide_id)
);
The same goes for the image_types and image_languages. I hope you understand the logic. And make sure to add proper FOREIGN KEY constraints. Also, it is a good idea to CREATE INDEX on the image_id columns of the subordinate tables.
Now, you have 1 row per each parameter in the related tables. Managing the contents should be easy: INSERT new records when some features are selected and DELETE them when those are deselected. The query (based on the outlined 2 tables) should be:
SELECT i.image_id, i.image_name,
group_concat(s.slide_id) AS slides
FROM images i
LEFT JOIN slides s USING (image_id)
GROUP BY i.image_id;
Some notes:
It is safe to do GROUP BY only by image_id, as it is a PRIMARY KEY of the iamges and thus it will guarantee single-row groupping;
If you'd like to have slide_id (also language_id, type_id and others) starting from 1 for each of the images, you might go for a 2-field primary keys in the subordinate table, like PRIMARY KEY (image_id, slide_id).
EDIT:
A note on the many-to-many relations. If you happen to have 2 sets of related data, like images can have many slides and slide_id can be shared by many image_id, then you need an extra table:
CREATE TABLE images (
image_id integer,
image_name varchar(100),
PRIMARY KEY(image_id)
);
CREATE TABLE slides (
slide_id integer,
slide_name varchar(100),
PRIMARY KEY(slide_id)
);
CREATE TABLE image_slides (
image_id integer,
slide_id integer,
create_dt timestamp,
PRIMRY KEY (image_id, slide_id)
);

is it possible to transfer table data from one table to another?

is it possible to copy data from a table to another table?.
here is my example. i have two tables, warehouse and showroom
my warehouse table has (product_id and stock_quantity) and my showroom table has (product_id(fk from warehouse), stock_transferred )..
for example in warehouse table
product_id stock_quantity
1 10
2 20
how can I transfer product_id(1)with stock_quantity(5) in showroom table and still retain the data in warehouse table?
so after transferring data my warehouse table becomes these:
product_id stock_quantity
1 5
2 20
and my showroom table becomes these:
product_id stock_transferred
1 5
how can i do these in a php form?for example i have a text input in which the user can specify how many stocks he will transfer to showroom table.
sorry I cant explain well Im not good in english.
BEGIN TRAN
INSERT INTO showroom
SELECT product_id, #ValueToBeReduced FROM warehouse
WHERE product_id = 1
-- error handling
UPDATE warehouse
SET stock_quantity = stock_quantity - #ValueToBeReduced
INNER JOIN showroom
ON warehouse.product_id = showroom.product_id
AND showroom.product_id = 1
-- error handling
COMMIT TRAN
You can use insert into(select...)

MySQL insert to multiple tables (relational)

tbl_product
Name | Creator | UID | Salerank
tbl_price
Supplier | Price | UID
I want to insert a product and then insert multiple prices into a seperate table. How is it possible to ensure that both tables had the same UID ideally an auto increment field? I will be using PHP alongside MySQL.
Thanks,
J
Make UID an auto_increment primary key on the products table, but just a regular primary key on the prices table (no auto_increment). After you insert itnto products, use the PHP command mysql_insert_id(). This will get the ID generated from the last query, which will be your UID generated on the products table. Assign it a variable and use it in your insert statement on the prices table.
http://php.net/manual/en/function.mysql-insert-id.php
Use a GUID for the UID, or better, insert your products and the insert the prices using e.g. the name of the product (assuming unique) to look up the relevant product UID.

Categories