How to create a trigger for delete php myadmin - php

I have two tables A and B. If I remove a entry in the table A, I want to update the status of the entry in the table B using the user id. I'm using this code:
CREATE TRIGGER blockuserundo BEFORE DELETE ON user_blocked
FOR EACH ROW BEGIN
UPDATE members SET ty_status = '1' WHERE user_id = OLD.block_user_id ;
END;
It shows an error like:
no new row in the trigger delete
Please guide me to write the query for the above scenario.

You need to set the delimiter to something other then ;
DELIMITER |
CREATE TRIGGER blockuserundo BEFORE DELETE ON user_blocked
FOR EACH ROW BEGIN
UPDATE members SET ty_status = '1' WHERE user_id = OLD.block_user_id ;
END;
|
DELIMITER ;
Code below works as expected:
DROP TABLE IF EXISTS user_blocked;
CREATE TABLE user_blocked
(
block_user_id INT
);
DROP TABLE IF EXISTS members;
CREATE TABLE members
(
user_id INT,
ty_status CHAR(1)
);
INSERT user_blocked
VALUES (1),(2),(3),(4),(5);
INSERT members
VALUES (1, '0'),(2, '0'),(3, '0'),(8, '0'),(9, '1');
DELIMITER |
CREATE TRIGGER blockuserundo BEFORE DELETE ON user_blocked
FOR EACH ROW BEGIN
UPDATE members SET ty_status = '1' WHERE user_id = OLD.block_user_id ;
END;
|
DELIMITER ;
SELECT * FROM members;
DELETE FROM user_blocked WHERE block_user_id IN(1,2);
SELECT * FROM members;

Related

Add dynamic column to existing MySQL table?

just wondering how to insert dynamic column to existing MySQL table? For example: I already have "sampletable" and I want to make input fields that can add dynamic column to the existing table, example: column1, column2, column3. How to do that with dynamic numbering?
I would agree with #Barmar that your SQL table structure is wrong if you are trying to do this. What you are trying to do in this case is what's called a "one to many" relationship. This is usually achieved by doing something like the following.
Table 1: Contains columns for all the usual data (non-"dynamic" columns in your terms), and a unique ID column which all good database tables should have
Table 2: An ID column, and column that refers to the ID column on table one and a column for the data that goes in the dynamic column.
Now you can store your values that you would normally store in "dynamic columns" in individual rows on the second table.
Example
// sample:
//
// | id | name |
//
// dynamic_values:
//
// | id | sample_id | value |
// Selecting data
SELECT * FROM sample WHERE id = 1;
SELECT * FROM dynamic_values WHERE sample_id = 1;
// Querying on "dynamic columns"
SELECT * FROM sample s LEFT JOIN dynamic_values d ON d.sample_id = s.id WHERE d.value = 'something';
Try This set of code for Dynamic Column Creation for Existing Table.
SET SQL_SAFE_UPDATES = 0;
Drop TEMPORARY table if exists Temp_Report;
CREATE TEMPORARY TABLE Temp_Report (Report_Date Date);
Drop TEMPORARY table if exists Temp_Product_Tax;
CREATE TEMPORARY TABLE Temp_Product_Tax as SELECT concat(REPLACE(Tax_category,' ','_'),'|',Taxvalue) as 'Tax_category',Taxvalue FROM tax_category c left join taxmaster t on c.id=t.catid ; -- where c.is_Product =1
select * from Temp_Product_Tax;
set Count_1=(SELECT COUNT(*) FROM Temp_Product_Tax);
set Var_1=0;
While(Count_1>Var_1) do
set #Col_Name=Concat( Var_1+1,'_',REPLACE((select Tax_category from Temp_Product_Tax limit Var_1,1),'.','_'),' Double(15,2)');
set #Col_Name=Concat('ALTER TABLE Temp_Report ADD COLUMN ', #Col_Name) ;
PREPARE stmt FROM #Col_Name;
EXECUTE stmt;
set Var_1=Var_1+1;
END While;
select * from Temp_Report;
SET SQL_SAFE_UPDATES = 1;
In fact, what you intend to do, ie, adding dynamic columns is not at all a good practice I think. Anyway
You can do that using ALTER TABLE
for($i=1;$i<4;$i++){
mysqli_query("ALTER TABLE mytable ADD COLUMN `input.$i` VARCHAR(40)",$db_con);
}
But I would suggest the same way, which is BARMER mentioned in the above comments.

Update another table when another one is updated

I'm not quite figuring out how to do what I'm after.So what I'm making is an online game.When a user buy's a new car I do an INSERT:
$c->query("INSERT INTO user_cars (carid, userid, acc, speed) VALUES ('$buyid','$id','$acc','$speed')");
Now I have another table that I need to insert info to right after the query above FROM the query above.What I need is the carid .The user can have more than 2 cars.What should I do now?
You have multiple options:
You can build a trigger to insert a new row in table2, when row is inserted in the cars table (Read more here http://dev.mysql.com/doc/refman/5.5/en/trigger-syntax.html)
There is this function mysql_insert_id() which returns the last inserted id ( Read more here http://php.net/manual/en/function.mysql-insert-id.php )
If you use PDO , there is a smillar command for it
etc.
This is a basic demonstration of the trigger you would want to create. For illustrative purposes I've also included the ddl and an example insert into your user_cars table to show that another table, which I've called "your_other_table" receives the insert (just the carid value) of an insert going into the user_cars table.
Fiddle:
http://sqlfiddle.com/#!9/f76a7/1/0
(notice how "your_other_tabe" has one row with the carid of the insert into "user_cars", despite having no direct inserts into itself)
delimiter //
create table user_cars
(
carid int,
userid int,
acc int,
speed int,
constraint id_pk primary key (carid, userid)
)//
create table your_other_table
(
carid int
)//
create trigger your_trigger_name before insert on user_cars
for each row begin
insert into your_other_table (carid)
values (new.carid);
end
//
insert into user_cars values
(1, 2, 3, 99)//
delimiter ;
select *
from your_other_table;
Output:
| CARID |
|-------|
| 1 |
This is the only portion of the above sql that creates the trigger:
delimiter //
create trigger your_trigger_name before insert on user_cars
for each row begin
insert into your_other_table (carid)
values (new.carid);
end
//
delimiter ;

MySQL procedure returning incorrect value to PHP

I have this stored procedure that inserts data into the event table. The problem is that the value returned to PHP in select lastNum; is 1 lower (inserted as 2 but will return 1) than when it is used in the previous insert statement. This doesn't make any sense to me as the value is not changed in between the 2 lines.
DROP PROCEDURE IF EXISTS `insertEvent`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `insertEvent`(ptitle varchar(500), pdescription varchar(500), pxcoord int(4), pycoord int(4), ptype char(1), pnumber int(11))
begin
declare numExists int(1);
declare lastNum int(9);
select count(*) from event where `number`=pnumber;
select insAndIncEventId() into lastNum from dual;
if numExists > 0 then
update event set `number`=`number`+1 where `number`>=pnumber;
end if;
insert into event (id, title, description, xcoord, ycoord, `type`, `number`) values (lastNum, ptitle, pdescription, pxcoord, pycoord, ptype, pnumber);
select lastNum;
end$$
drop function if exists `insAndIncEventId`$$
create function `insAndIncEventId`() returns int(9)
begin
declare event_id int(9);
select nextId into event_id from eventid;
update eventid set nextid=nextid+1;
return event_id;
end$$
The PHP is as follows:
$eventid=$eventidstmt->fetch(PDO::FETCH_BOTH);
fb("event id count from sql:".count($eventid));
fb("event id from sql:".$eventid[0]);

Insert into 2 table and set both foreign key auto increment

I have a database with two tables. When a user posts an article, it will be inserted into both tables, (2 queries in one file)
I use post_id as foreign key, both tables post_id auto increment. Will foreign keys be messed up? For example if users A and B query the database at the same time.
Table 1
post_id user...
1 A
2 B
Table 2
post_id content...
1 A
2 B
First off you can't have auto increment on both tables.
Usually, what you do is insert in table 1, get the ID of the just inserted row.
Then you use this ID, to insert in table 2 which references table 1.
See: mysqli::$insert_id at
http://www.php.net/manual/en/mysqli.insert-id.php
Example:
$query = "INSERT INTO table1(user,whatever) VALUES ('A','something')";
$mysqli->query($query);
printf ("New Record has id %d.\n", $mysqli->insert_id);
$query = "INSERT INTO table2(post_id,content) VALUES ($mysqli->insert_id,'This is content')";
$mysqli->query($query);
You could also do this using a stored procedure based on: stackoverflow.com/a/1723325/1688441
DELIMITER //
CREATE PROCEDURE new_post_with_content(
user_id CHAR(5), content_text CHAR(100)
BEGIN
START TRANSACTION;
INSERT INTO table1 (user)
VALUES(user_id);
INSERT INTO table2 (post_id, content)
VALUES(LAST_INSERT_ID(), content_text);
COMMIT;
END//
DELIMITER ;
And you call it like so:
CALL new_engineer_with_task('A','This is the content');
Why not use table1 as user table and second with posts?
users
user_id(autoinc) username
1 A
2 B
3 C
posts
post_id(autoinc) user_id posts_text
1 2 text
2 1 other text

Removing duplicate field entries in SQL

Is there anyway I can erase all the duplicate entries from a certain table (users)? Here is a sample of the type of entries I have. I must say the table users consists of 3 fields, ID, user, and pass.
mysql_query("DELETE FROM users WHERE ???") or die(mysql_error());
randomtest
randomtest
randomtest
nextfile
baby
randomtest
dog
anothertest
randomtest
baby
nextfile
dog
anothertest
randomtest
randomtest
I want to be able to find the duplicate entries, and then delete all of the duplicates, and leave one.
You can solve it with only one query.
If your table has the following structure:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL auto_increment,
`username` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
you could do something like that (this will delete all duplicate users based on username with and ID greater than the smaller ID for that username):
DELETE users
FROM users INNER JOIN
(SELECT MIN(id) as id, username FROM users GROUP BY username) AS t
ON users.username = t.username AND users.id > t.id
It works and I've already use something similar to delete duplicates.
You can do it with three sqls:
create table tmp as select distinct name from users;
drop table users;
alter table tmp rename users;
This delete script (SQL Server syntax) should work:
DELETE FROM Users
WHERE ID NOT IN (
SELECT MIN(ID)
FROM Users
GROUP BY User
)
I assume that you have a structure like the following:
users
-----------------
| id | username |
-----------------
| 1 | joe |
| 2 | bob |
| 3 | jane |
| 4 | bob |
| 5 | bob |
| 6 | jane |
-----------------
Doing the magic with temporary is required since MySQL cannot use a sub-select in delete query that uses the delete's target table.
CREATE TEMPORARY TABLE IF NOT EXISTS users_to_delete (id INTEGER);
INSERT INTO users_to_delete (id)
SELECT MIN(u1.id) as id
FROM users u1
INNER JOIN users u2 ON u1.username = u2.username
GROUP BY u1.username;
DELETE FROM users WHERE id NOT IN (SELECT id FROM users_to_delete);
I know the query is a bit hairy but it does the work, even if the users table has more than 2 columns.
You need to be a bit careful of how the data in your table is used. If this really is a users table, there is likely other tables with FKs pointing to the ID column. In which case you need to update those tables to use ID you have selected to keep.
If it's just a standalone table (no table reference it)
CREATE TEMPORARY TABLE Tmp (ID int);
INSERT INTO Tmp SELECT ID FROM USERS GROUP BY User;
DELETE FROM Users WHERE ID NOT IN (SELECT ID FROM Tmp);
Users table linked from other tables
Create the temporary tables including a link table that holds all the old id's and the respective new ids which other tables should reference instead.
CREATE TEMPORARY TABLE Keep (ID int, User varchar(45));
CREATE TEMPORARY TABLE Remove (OldID int, NewID int);
INSERT INTO Keep SELECT ID, User FROM USERS GROUP BY User;
INSERT INTO Remove SELECT u1.ID, u2.ID FROM Users u1 INNER JOIN Keep u2 ON u2.User = u1.User WHERE u1.ID NOT IN (SELECT ID FROM Users GROUP BY User);
Go through any tables which reference your users table and update their FK column (likely called UserID) to point to the New unique ID which you have selected, like so...
UPDATE MYTABLE t INNER JOIN Remove r ON t.UserID = r.OldID
SET t.UserID = r.NewID;
Finally go back to your users table and remove the no longer referenced duplicates:
DELETE FROM Users WHERE ID NOT IN (SELECT ID FROM Keep);
Clean up those Tmp tables:
DROP TABLE KEEP;
DROP TABLE REMOVE;
A very simple solution would be to set an UNIQUE index on the table's column you wish to have unique values. Note that you subsequently cannot insert the same key twice.
Edit: My mistake, I hadn't read that last line: "I want to be able to find the duplicate entries".
I would get all the results, put them in an array of IDs and VALUES. Use a PHP function to work out the dupes, log all the IDs in an array, and use those values to delete the records.
I don't know your db schema, but the simplest solution seems to be to do SELECT DISTINCT on that table, keep the result in a variable (i.e. array), delete all records from the table and then reinsert the list returne by SELECT DISTINCT previously.
The temporary table is an excellent solution, but I'd like to provide a SELECT query that grabs duplicate rows from the table as an alternative:
SELECT * FROM `users` LEFT JOIN (
SELECT `name`, COUNT(`name`) AS `count`
FROM `users` GROUP BY `name`
) AS `grouped`
WHERE `grouped`.`name` = `users`.`name`
AND `grouped`.`count`>1
Select your 3 columns as per your table structure and apply condition as per your requirements.
SELECT user.userId,user.username user.password FROM user As user
GROUP BY user.userId, user.username
HAVING (COUNT(user.username) > 1));
Every answer above and/or below didn't work for me, therefore I decided to write my own little script. It's not the best, but it gets the job done.
Comments are included throughout, but this script is customized for my needs, and I hope the idea helps you.
I basically wrote the database contents to a temp file, called the temp file, applied the function to the called file to remove the duplicates, truncated the table, and then input the data right back into the SQL. Sounds like a lot, I know.
If you're confused as to what $setprofile is, it's a session that's created upon logging into my script (to establish a profile), and is cleared upon logging out.
<?php
// session and includes, you know the drill.
session_start();
include_once('connect/config.php');
// create a temp file with session id and current date
$datefile = date("m-j-Y");
$file = "temp/$setprofile-$datefile.txt";
$f = fopen($file, 'w'); // Open in write mode
// call the user and pass via SQL and write them to $file
$sql = mysql_query("SELECT * FROM _$setprofile ORDER BY user DESC");
while($row = mysql_fetch_array($sql))
{
$user = $row['user'];
$pass = $row['pass'];
$accounts = "$user:$pass "; // the white space right here is important, it defines the separator for the dupe check function
fwrite($f, $accounts);
}
fclose($f);
// **** Dupe Function **** //
// removes duplicate substrings between the seperator
function uniqueStrs($seperator, $str) {
// convert string to an array using ' ' as the seperator
$str_arr = explode($seperator, $str);
// remove duplicate array values
$result = array_unique($str_arr);
// convert array back to string, using ' ' to glue it back
$unique_str = implode(' ', $result);
// return the unique string
return $unique_str;
}
// **** END Dupe Function **** //
// call the list we made earlier, so we can use the function above to remove dupes
$str = file_get_contents($file);
// seperator
$seperator = ' ';
// use the function to save a unique string
$new_str = uniqueStrs($seperator, $str);
// empty the table
mysql_query("TRUNCATE TABLE _$setprofile") or die(mysql_error());
// prep for SQL by replacing test:test with ('test','test'), etc.
// this isn't a sufficient way of converting, as i said, it works for me.
$patterns = array("/([^\s:]+):([^\s:]+)/", "/\s++\(/");
$replacements = array("('$1', '$2')", ", (");
// insert the values into your table, and presto! no more dupes.
$sql = 'INSERT INTO `_'.$setprofile.'` (`user`, `pass`) VALUES ' . preg_replace($patterns, $replacements, $new_str) . ';';
$product = mysql_query($sql) or die(mysql_error()); // put $new_str here so it will replace new list with SQL formatting
// if all goes well.... OR wrong? :)
if($product){ echo "Completed!";
} else {
echo "Failed!";
}
unlink($file); // delete the temp file/list we made earlier
?>
This will work:
create table tmp like users;
insert into tmp select distinct name from users;
drop table users;
alter table tmp rename users;
If you have a Unique ID / Primary key on the table then:
DELETE FROM MyTable AS T1
WHERE MyID <
(
SELECT MAX(MyID)
FROM MyTable AS T2
WHERE T2.Col1 = T1.Col1
AND T2.Col2 = T1.Col2
... repeat for all columns to consider duplicates ...
)
if you don't have a Unique Key select all distinct values into a temporary table, delete all original rows, and copy back from temporary table - but this will be problematic if you have Foreign Keys referring to this table

Categories