How to do 2 sql command - php

the first sql command is:
INSERT INTO table1(post) values('$post');
and after insert $post I want to update a column in another table
so I used:
UPDATE table2 SET score='$score' where name='$name';
how do I combine these 2 command or do them at the same time ?
I am new to mysql :)
here is what I want:
a user go to my website and post an string after post it the score of that user will be update

If for every insert you update, you could add triggers to your database.
Code :
delimiter |
CREATE or REPLACE TRIGGER TriggerName
AFTER INSERT
ON table1
BEGIN
UPDATE table2 SET score=score + 1 WHERE name=INSERTED.user_id
# INSERTED is the row added to table1
END;
delimiter ;
If you have the user id field in table1, this should work.
Otherwise, if you use a relation-table, like user_post (id, user_id, post_id), you have to declare a variable to store the id temporarily

If you don't like maintaining two applications from now on (the one you have and the one you create in the database by adding triggers or functions), there is a simpler solution:
Use only one piece of PHP code to add this stuff to the database (like a function or class' method), and simply send the two queries one after the other.
For extra data consistency, you should use a transaction, which is simply two more queries, or an appropriate usage of the database classes. For example, MySQLi has http://php.net/manual/en/mysqli.begin-transaction.php to start the transaction and http://php.net/manual/en/mysqli.commit.php to end it (or http://php.net/manual/en/mysqli.rollback.php to undo).
function writePostWithScore($post, $name, $score) {
// have the mysqli connection object somewhere
$mysqli->begin_transaction(MYSQLI_TRANS_START_READ_WRITE);
$mysqli->query("INSERT INTO table1 (post) values('".$mysqli->real_escape_string($post)."')");
$mysqli->query("UPDATE table2 SET score='".$mysqli->real_escape_string($score)."' where name='".$mysqli->real_escape_string($name)."'");
$mysqli->commit();
}

I always create functions. Create 2 functions. One that insert, the otherone will update. Call what you need.

Related

Syncing two rows from different tables in the same MySQL database

I have a table named clients, in that table there's two columns of importance; id and client. I have a secondary table in the same database named calendar. I really want the two columns of id and client in the calendar table to sync with the ones in client table.
Right now I am using this PHP to execute this in MySQL:
INSERT IGNORE INTO calendar (id, client) SELECT id, client FROM clients;
Is there a better way of accomplish this task? Maybe a built in function in MySQL that I have overlooked or something like that?
Use Triggers : The MySQL trigger is a database object that is associated with a table. It will be activated when a defined action is executed for the table.
The trigger can be executed when you run one of the following MySQL statements on the table: INSERT, UPDATE and DELETE and it can be invoked before or after the event.
You can make trigger when you insert or update a row in main table and make the changes in another table
Example:
DELIMITER $$
CREATE TRIGGER my_sync_trigger
AFTER INSERT ON `clients` for each row
begin
INSERT INTO calender (id,client)
Values (new.id, new.client);
END$$
DELIMITER ;
"new" stands for the new value inserted into clients table. The same value will be inserted into id and client column in calender.
Note: single quotes are removed from table name because quotes effectively make it a string literal instead of a proper identifier.
DELIMITER command will change the ending of each statement from ";" to "$$" so that MySQL is not confused with ";" inside and outside the trigger
Make similar triggers for update and delete also
Simple guide for examples and syntax:
http://www.mysqltutorial.org/create-the-first-trigger-in-mysql.aspx

Alternative to block a table

I have a table called 'messages' (INNODB) where the user can insert their own posts.
I want to put a limitation. In my php script when the table gets to 10 records, you can not add more. The logic of the program is more or less as follows.
Step 1. I run a query to count the lines that are in the table.
Step 2. Recovered that value, I decide whether to insert a new post.
My difficulty is in properly managing the possibility of two user who do the same thing simultaneously. If the user A is in step 1 while user B has just finished entering the tenth post, user A will include the eleventh.
How to avoid it?
You can create CHAR(1) NOT NULL field and cover it with UNIQUE INDEX. This will prevent of inserting more than 10 rows.
Other solution that could work would be to create BEFORE INSERT trigger that checks number of rows and raises error if there are more than 10 (look here for sample) (but in this case you can fail with condition races).
In order to allow you to change your threshold value for the table, you can use a trigger. Because MySQL triggers don't have a "prevent INSERT" option, you need a value in your table set to NOT NULL. The trigger can then set the inserted value for that column to NULL which will prevent the INSERT if your condition check fails.
A trigger like this:
CREATE TRIGGER block_insert
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
DECLARE count INT;
SELECT COUNT(*)
FROM table_name INTO count;
IF count >= 10
THEN
SET NEW.non_nullable_value = NULL;
END IF;
END;
would fail if you inserted an 11th row, like this:
ERROR 1048 (23000): Column 'non_nullable_value' cannot be null
You may wish to set the non-nullable column's name to something that represents its use. You could improve this by having the trigger pull the limit value from a configuration table.
Update
To avoid having to use the non-nullable columns, you could alternatively create an error procedure, and CALL it from your trigger - similar to the example in the "Emulating Check Constraints" section of this page - they're referencing Oracle databases, where a check constraint achieves what you want, but MySQL doesn't support them.
The "error procedure" in the example performs an INSERT of a duplicate row into an error table, causing a unique key error and stops the parent transaction also.
Update 2
As pointed out in the comment below, multiple simultaneous transactions may get round the checks - you'll have to use LOCK TABLES <name> WRITE in order to ensure that they can't.
2/ You can also lock the MySQL table.
execute : LOCK TABLES my_table
Then do your business rules.
execute : UNLOCK TABLES
This also ensure that each action is sequentially executed. (but you have to deal with performance overhead)
Hope this could be useful.
Updated since the comments below : transaction don't work in this case
1/ You are using InnoDB, you can also use database transaction
Open transaction
Then do your business rules.
Commit or rollback your transaction
This will ensure that each action are executed one after another.

incrementing a field in a table when insertion in another table occurs

Let's say I have two tables as shown:
user
id plan course_limit username
10 0 ahmad
note: plan is enum field containing '','a','b','c'.
course
id user_id username
1 10 ahmad
Now I want when a user insert into course as shown I want the course_limit to increment by 1 for that user so that I can apply a limit.
You can create a trigger with the following code.
CREATE
DEFINER = 'root'#'localhost'
TRIGGER databasename.AI_course_each
AFTER INSERT
ON databasename.course
FOR EACH ROW
BEGIN
UPDATE user SET user.course_limit = user.course_limit + 1
WHERE user.user_id = new.user_id;
END;
Some explanation
You create a trigger that fires once for every row FOR EACH ROW that is inserted AFTER INSERT into table course.
When you insert into the table you can trigger BEFORE and AFTER the insert is done.
If you want to be able to prevent the insert you fire before, if you just want to do useful work, you fire after.
The inserted fields can be accessed via a dummy table 'new'.
So here after each insert the UPDATE statement gets executed.
More trigger options
You can also use triggers BEFORE UPDATE, AFTER UPDATE,BEFORE DELETE and AFTER DELETE.
In the update and delete cases you get an extra dummy table old that you can use to refer to the data in the table before the update or delete happened.
Lots more is possible, but I'll keep it simple for now.
See http://forge.mysql.com/wiki/Triggers for more info.
Using a trigger should solve your problem : with that, you'll be able to register SQL code, on your MySQL server, that runs when certain events occur (like insertion).

Best way to INSERT autoincrement field? (PHP/MySQL)

I have to insert data into two tables, Items and Class_Items. (A third table, Classes is related here, but is not being inserted into).
The primary key of Items is Item_ID, and it's an auto-incrementing integer. Aside from this primary key, there are no unique fields in Items. I need to know what the Item_ID is to match it to Classes in Class_Items.
This is all being done through a PHP interface. I'm wondering what the best way is to insert Items, and then match their Item_ID's into Class_Items. Here are the two main options I see:
INSERT each Item, then use mysql_insert_id() to get its Item_ID for the Class_Items INSERT query. This means one query for every Item (thousands of queries in total).
Get the next Autoincrement ID, then LOCK the Class_Items table so that I can just keep adding to an $item_id variable. This would mean just two queries (one for the Items, one for the Class_Items)
Which way is best and why? Also, if you have an unlisted alternative I'm open to whatever is most efficient.
The most efficient is probably going to be to use parameterized queries. That would require using the mysqli functions, but if you're to the point of needing to optimize this kind of query you should think about being there anyway.
No matter how you cut it, you've got two inserts to make. Doing the first, grabbing the new ID value as you've described (which imposes insignificant overhead, because the value is on hand to mysql already,) and using it in the second insert is pretty minimal.
I would investigate using stored procedures and/or transactions to make sure nothing bad happens.
I'm working on a project with mysql and what I did is the following (without using autoincrement fields):
1- I created a table called SEQUENCE with one field of type BIGINT called VALUE with an initial value of 1. This table will store the id value that will be incremented each time you insert a new record.
2- Create a store procedure and handle the id increment inside it within a transaction.
Here is an example.
CREATE PROCEDURE `SP_registerUser`(
IN _username VARCHAR(40),
IN _password VARCHAR(40),
)
BEGIN
DECLARE seq_user BIGINT;
START TRANSACTION;
#Validate that user does not exist etc..........
#Register the user
SELECT value FROM SEQUENCE INTO seq_user;
UPDATE SECUENCE SET value = value + 1;
INSERT INTO users VALUES(seq_user, _username, SHA1(_password));
INSERT INTO user_info VALUES(seq_user, UTC_TIMESTAMP());
COMMIT;
END //
In my case I want to store the user id in two different tables (users and user_info)

Retrieving the index of an inserted row

I'm trying to keep the database tables for a project I'm working on nice and normalized, but I've run into a problem. I'm trying to figure out how I can insert a row into a table and then find out what the value of the auto_incremented id column was set to so that I can insert additional data into another table. I know there are functions such as mysql_insert_id which "get the ID generated from the previous INSERT operation". However, if I'm not mistaken mysql_insert_id just returns the ID of the very last operation. So, if the site has enough traffic this wouldn't necessarily return the ID of the query you want since another query could have been run between when you inserted the row and look for the ID. Is this understanding of mysql_insert_id correct? Any suggestions on how to do this are greatly appreciated. Thanks.
LAST_INSERT_ID() has session scope.
It will return the identity value inserted in the current session.
If you don't insert any rows between INSERT and LAST_INSERT_ID, then it will work all right.
Note though that for multiple value inserts, it will return the identity of the first row inserted, not the last one:
INSERT
INTO mytable (identity_column)
VALUES (NULL)
SELECT LAST_INSERT_ID()
--
1
INSERT
INTO mytable (identity_column)
VALUES (NULL), (NULL)
/* This inserts rows 2 and 3 */
SELECT LAST_INSERT_ID()
--
2
/* But this returns 2, not 3 */
You could:
A. Assume that won't be a problem and use mysql_insert_id
or
B. Include a timestamp in the row and retrieve the last inserted ID before inserting into another table.
The general solution to this is to do one of two things:
Create a procedural query that does the insert and then retrieves the last inserted id (using, ie. LAST_INSERT_ID()) and returns it as output from the query.
Do the insert, do another insert where the id value is something like (select myid from table where somecolumnval='val')
2b. Or make the select explicit and standalone, and then do the other inserts using that value.
The disadvantage to the first is that you have to write a proc for each of these cases. The disadvantage to the second is that some db engines don't accept that, and it clutters your code, and can be slow if you have to do a where on multiple columns.
This assumes that there may be inserts between your calls that you have no control over. If you have explicit control, one of the other solutions above is probably better.

Categories