I'm new to both PHP and MySQL and I have a pretty complicated task to do for my current know-how. It goes like this:
I'm trying to create a data-driven website with a hand made CMS that will allow a user with no knowledge of web design/web development to manage it. Where I'm stuck is when I try to create a query to handle the data inserted to the database. It is a bookstore and I'm inserting books in the database. I thought of creating 3 tables, one to store the books themselves, one to store the categories these books belong to (f.e. literature, mystery, fantasy, etc) and, since the relation between these two tables is many-to-many relationship, I also created a lookup table to link these two, using 2 columns populated with 2 foreign keys representing the IDs of the two tables.
The problem is I can't find how to insert multiple rows with same ID (the book ID) on one column and different second column (the category ID). The categories will be picked in an HTML form via checkboxes. I' ve seen in several posts here I need to make an array in PHP script to store the data from the checkboxes the user picked, but I have absolutely no clue on how to structure the query that will turn these checkboxes into multiple MySQL table rows.
I've seen people suggesting imploding the values, but that would store multiple values in one row, or am I mistaken? Because that is not what I want, I want (if f.e. the user checked 3 categories checkboxes) to create 3 rows in the lookup table.
Thanks in advance for your time seeing my question.
$categories = array(1,2,3,4);
$bookId = 5;
foreach ($categories as $categoryId) {
$data = array(
'book_id' => (int)$bookId,
'category_id' => (int)$categoryId
);
$query = "INSERT INTO `lookup` SET ";
$fields = array();
foreach ($data as $field => $value) {
$fields[] = "`$field` = '$value'";
}
$fields = implode(', ', $fields);
$query .= $fields;
mysql_query($query);
}
You can build up an insert using implode to insert many rows. Something like this:-
<?php
$Category = 123;
$Books = array(1,2,3,4,5,6,7,8,9,10);
$sql = "INSERT INTO book_category_link(NULL, category_id, book_id)
VALUES ($Category".implode("),($category", $Books).")";
?>
Or if you want to use the existing tables to get the ids then something like this:-
<?php
$Category = (123, 456, 789);
$Books = array(1,2,3,4,5,6,7,8,9,10);
$sql = "INSERT INTO book_category_link(NULL, category_id, book_id)
SELECT NULL, categories.id, books.id
FROM books
CROSS JOIN categories
WHERE books.id IN (".implode(",", $Books).")
AND categories.id IN (".implode(",", $Category).")";
?>
It's really simple. First you insert the the book into the books table and then get the ID of it. Let's say for this example it is the ID 5.
Lets say you have the following categorie id's from the checkboxes: array(21, 42, 64);
Now you can construct a query like this to insert them into the lookup table:
INSERT INTO `lookup` (book_id, category_id') VALUES (5, 21), (5, 42), (5, 64);
No, you can't insert into multiple tables in one MySQL command. You can however use transactions.
INSERT ...
SELECT LAST_INSERT_ID() INTO #mysql_variable_here;
INSERT INTO table2 (#mysql_variable_here, ...);
INSERT INTO table3 (#mysql_variable_here, ...);
if you want to add multiple rows inserted then u can use the syntax
INSERT INTO table (col1, col2) VALUES ('value', 'value'), (value, 'value');
The very basic idea is to iterate a loop on the categories submitted and run an insert query containing category ID and book ID into the lookup table.
$bookID= $_POST['bookid'];
foreach ($categories as $category) {
mysql_query("INSERT INTO lookup(bookid,categoryid) values($bookID,$catetory)");
}
Related
Bit new to MYSQL and PHP - I have the following code that will create a new record in multiple tables that I have setup however I need to merge the following code together somehow as it creates separate rows instead of one record
$sql .=("INSERT INTO orders (customer_id) SELECT customer_id FROM
customer_details;");
foreach($result as $item){
$mysql_desc = $item['product_description'];
$mysql_mode = $item['delivery_mode'];
$mysql_cost = $item['course_cost'];
$sql .=("INSERT INTO orders(product_description, delivery_mode, course_cost) VALUES('$mysql_desc', '$mysql_mode', '$mysql_cost');");
}
The result I'm getting:
Based on your data I assume that you want to insert the customer id and the values from php into the same record. In this case you need to combine them into the same insert ... select ... statement:
$sql .=("INSERT INTO orders(customer_id, product_description, delivery_mode, course_cost) select customer_id, '$mysql_desc', '$mysql_mode', '$mysql_cost' from customer_details;");
Couple of things to note:
This insert ... select ... statement will insert the same records for all customers in the customer details table. I'm not sure if this is your ultimate goal.
Pls consider the advices made in the comments regarding the old mysql API and the use of prepared statements.
To put this more into what I would expect to happen, something along the lines of - prepare statement, then loop through each item and add in new row...
$insert = $connection->prepare("INSERT INTO orders (customer_id,product_description, delivery_mode, course_cost)
VALUES (?,?,?,?)");
foreach($result as $item){
$customerID = 1; // Have to ensure this is what your after
$mysql_desc = $item['product_description'];
$mysql_mode = $item['delivery_mode'];
$mysql_cost = $item['course_cost'];
$insert->execute([customerID,mysql_desc,mysql_mode,mysql_cost]);
}
I have three tables in database:
trips(trip_id(pk), trip_name(unique), user_id(fk))
places(place_id(pk), place_name(unique))
trips_places_asc(trip_id(fk), place_id(fk))
Since, many trips can have many places, I have one junction table as above.
Now, if user insert places to the trip, the places will be added to places table and the trip will be associated with the places in trips_places_asc table.
So, if i write query like:
INSERT INTO places (place_name)
VALUES ('XYZ')
INSERT INTO trips (trip_name)
VALUES ('MyTrip')
Then, How to store trip_id and place_id in Junction or Association table trips_places_asc?
will I have to fire two queries? plz help.
Note: There are many questions on SO like this one and this one. but, none of them have accepted answer or not even an answer. so, plz do not mark as duplicate.
Since you have place_name and trip_name as unique just do as:
insert into trips_places_asc ( trip_id, place_id )
values ( (select trip_id from trips where trip_name = 'MyTrip'),
(select place_id from places where place_name = 'XYZ') );
Or depending what comand you are using to insert (php command I mean) you can return the ids after the inserts and use it to run an insert command with it.
It will be like: (using mysqli* functions )
$query = "INSERT INTO trips (trip_name) values ('MyTrip')";
$mysqli->query($query);
$trip_id = $mysqli->insert_id;
$query2 = "INSERT INTO places (place_name) values ('XYZ')";
$mysqli->query($query2);
$place_id = $mysqli->insert_id;
$query3 = "insert into trips_places_asc ( trip_id, place_id ) ";
$query3 .= " values ($trip_id, $place_id)";
Note, I'm doing this directly from my mind, so maybe you have to adjust some syntax error or be concerned about prepared statements.
EDIT
Though I should add the proper documentation link about this command: http://php.net/manual/en/mysqli.insert-id.php
category --> `cat_id`,`name`
sub_category --> `sub_cat_id`,`name`
category_subcategory_association --> `cat_sub_cat_id`,`cat_id`,`sub_cat_id`
order_master --> `order_id`,`cat_sub_cat_id`,`cat_id`,`sub_cat_id`,`order_name`
These are the database tables which iam having while adding the orders into order_master table if we give cat_id,sub_cat_id while inserting into the table it should check the whether these ids are present in the association table or not,if the id is present in association table then we should get that association id and should insert into the orders table.
How can we do this can anyone help me
Thanks in advance.
You just need to check if it exists, if not - insert it into the the db and fetch the newest id.
I.E:
$cat_name = ; // your code
$sub_cat_name =; // your code
$query = mysql_query("SELECT cat_id FROM `category` AS `c` WHERE name = '$cat_name'");
if(!mysql_num_rows($query)) {
mysql_query("INSERT INTO category (name) VALUES ('$cat_name')");
$cat_id = mysql_insert_id();
} else
$cat_id = mysql_fetch_array($query);
// now do the same for the sub category and then insert it into to order_master
this is a general code, you need to customize it into your framework's standards.
hope it helped
you implement the checks via a select statement:
http://dev.mysql.com/doc/refman/5.1/de/select.html
running multiple sql queries, eg. a mixture of select and update statements requires you some knowledge on:
http://dev.mysql.com/doc/refman/5.0/en/innodb-transaction-model.html
http://php.net/manual/de/mysqli.multi-query.php
Lets say I have two tables. In table “category_name”, there are fields category_id and category name. In table “category_subscriptions” there are fields userid and category_number.
What I want to be able to do is to insert a row into category_subscriptions for each category_id using the same userid.
Consider “category_name” having the following values: 4, cars, 5, trucks, 6, trains
The ideal output table for “category_subscriptions (for userid=99) would have values: 99,4,99,5,99,6
Rather than use:
INSERT INTO category_subscriptions
VALUES (99,4)
INSERT INTO category_subscriptions
VALUES (99,5)
INSERT INTO category_subscriptions
VALUES (99,6)
I think I should be using a loop, as category.id won’t always be 4,5, &6. I’m just not sure if this is right and am hoping somebody can help. This is part of a plugin for Joomla 1.7/php.
Assuming you have an array $Categories including all your category_id's, you can do:
$user_id = 99;
$Categories = array(4, 5, 6);
$sql = "INSERT INTO category_subscriptions VALUES ";
$i = 0;
foreach ($Categories as $categorie) {
if ($i++) $sql .= ", ";
$sql .= "({$user_id}, {$categorie})";
}
The output of this code is
INSERT INTO category_subscriptions VALUES (99, 4), (99, 5), (99, 6)
Please note, that this builds a single query. You can insert multiple lines with one INSERT statement using VALUES (<line1>), (<line2>) ...
EDIT
If you really want to link your user to every existing category, you can also do it in plain SQL.
INSERT INTO `category_subscriptions` (`userid`, `category_number`)
SELECT 99, `category_id` FROM `category_name`
Maybe something like this :
<?php
$userID = '99';
$catID = array(4,5,6);
foreach($catID as $cid)
{
$value[] = '('.$userID,$cid.')';
}
mysql_query('INSERT INTO category_subscriptions (user_id,category_id) VALUES '.implode(',', $value));
?>
The script above will run mysql query :
INSERT INTO category_subscriptions VALUES (99,4), (99,5), (99,6)
I'm new to php. So, please forgive me if this seems like a dumb question.
Say i have a MySQL insert statement insert into table (a,b) values (1,2),(3,4),(5,6). table 'table' has a auto increment field called 'id'.
how can I retrieve all the ids created by the insert statement above?
It will be great if i get an example that uses mysqli.
You can't. I would suggest that you maintain your own ids (using guid or your own auto-increment table) and use it when you insert into the table.
But it's possible to get the auto-increment value for the last inserted using LAST_INSERT_ID():
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
AngeDeLaMort's answer is almost right. Certainly, the most appropriate way to deal with the problem is to insert one row at a time and poll the insert_id or generate the sequence elsewhere (which has additional benefits in terms of scalability).
I'd advise strongly against trying to determine the last insert_id and comparing this the most recent insert_id after the insert - there's just too may ways this will fail.
But...an alternative approach would be:
....
"INSERT INTO destn (id, data, other, trans_ref)
SELECT id, data, other, connection_id() FROM source";
....
"SELECT id FROM destn WHERE trans_ref=connection_id()";
....
"UPDATE destn SET trans_ref=NULL where trans_ref=connection_id()";
The second query will return the ids generated (note that this assumes that you use the same connection for all 3 queries). The third query is necessary because connection ids to go back into the pool when you disconnect (i.e. are reused).
C.
In some cases, if you have another identifier of sort such as a UserID, you could filter your query by UniqueID's greater than or equal to mysql_insert_id(), limit by the number of affected rows and only display those by the user. This would really only work inside of a transaction.
$SQL = "INSERT INTO Table
(UserID, Data)
VALUES
(1,'Foo'),
(1,'Bar'),
(1,'FooBar')";
$Result = mysql_query($SQL);
$LastID = mysql_insert_id();
$RowsAffected = mysql_affected_rows();
$IDSQL = "SELECT RecordID
FROM Table
WHERE UserID = 1
AND RecordID >= '$LastID'
LIMIT '$RowsAffected'";
$IDResult = mysql_query($IDSQL);
as a follow up to AngeDeLaMort:
You could seperate your inserts and do it something like this:
$data = array (
array(1,2),
array(3,4),
array(5,6)
);
$ids = array();
foreach ($data as $item) {
$sql = 'insert into table (a,b) values ('.$item[0].','.$item[1].')';
mysql_query ($sql);
$id[] = mysql_insert_id();
}
Now all your new id's are in the $id array.
Maybe I can do this
$insert = "insert into table (a,b) values (1,2),(3,4),(5,6)";
$mysqli->query($insert);
$rows_to_be_inserted=3;
$inserted_id = $mysqli->insert_id // gives me the id of the first row in my list
$last_row_id = ($inserted_id+$rows_to_be_inserted)-1;
$mysql->query("select * from table where id between $inserted_id and $last_row_id");
what to you guys say?