I how defined a procedure in MySql which has an input and input will be a name of column that will be added to table 'test1' but sql names that column input instead of using the value of input .how can i do this in the right way?
DELIMITER
CREATE PROCEDURE p1
(IN input CHAR(20))
BEGIN
ALTER TABLE test1
ADD COLUMN input char(20);
END
DELIMITER ;
You should google dynamic sql and read the manual https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-prepared-statements.html
In the meantime here's an example.
drop procedure if exists p;
alter table users
drop column abc;
DELIMITER $$
CREATE PROCEDURE p
(IN input CHAR(20))
BEGIN
#ALTER TABLE test1
#ADD COLUMN input char(20);
set #sql = concat('alter table users add column ',input,' char(20);');
select #sql;
prepare sqlstmt from #sql;
execute sqlstmt;
deallocate prepare sqlstmt;
END $$
DELIMITER ;
call p('abc');
describe users;
MariaDB [sandbox]> call p('abc');
+--------------------------------------------+
| #sql |
+--------------------------------------------+
| alter table users add column abc char(20); |
+--------------------------------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.42 sec)
MariaDB [sandbox]> describe users;
+---------------------+-------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+-------------+------+-----+-------------------+-------+
| id | int(11) | NO | PRI | NULL | |
| userName | varchar(60) | NO | | NULL | |
| photo | varchar(50) | YES | | NULL | |
| status | int(11) | YES | | NULL | |
| ts | datetime | YES | | CURRENT_TIMESTAMP | |
| events_participated | int(11) | YES | | NULL | |
| fb_uid | int(11) | YES | | NULL | |
| Column_name | varchar(10) | YES | | NULL | |
| post_type | varchar(10) | YES | | NULL | |
| password | varchar(8) | YES | | NULL | |
| abc | char(20) | YES | | NULL | |
+---------------------+-------------+------+-----+-------------------+-------+
11 rows in set (0.03 sec)
Related
I am trying to remove a column from a MySQL table that I am using with Handsontable. When I remove a column from the Handsontable, I can get the column's index using the afterRemoveCol() callback:
afterRemoveCol: function (index, amount) {
alert(index +' amount: '+amount);
}
I would like to remove the column using the column number (n) returned by this callback function from the MySQL table using something like:
ALTER TABLE tbl_Blah DROP COLUMN n;
So, if I want to drop column #3 from the MySQL table, How would I do this using just the column number?
To add to RMathis answer, you can do everything within SQL by also using SET to define the DROP string in conjuntion with PREPARE and EXECUTE
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE Table1
(`col1` varchar(1),
`col2` varchar(1),
`col3` varchar(1),
`col4` varchar(1),
`col5` varchar(1))
;
set #col = (select column_name
from information_schema.columns
where table_name='table1' and ordinal_position=3);
SET #s = CONCAT("alter table table1 drop column ", #col);
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Query 1:
desc table1
Results:
| COLUMN_NAME | COLUMN_TYPE | IS_NULLABLE | COLUMN_KEY | COLUMN_DEFAULT | EXTRA |
|-------------|-------------|-------------|------------|----------------|-------|
| col1 | varchar(1) | YES | | (null) | |
| col2 | varchar(1) | YES | | (null) | |
| col4 | varchar(1) | YES | | (null) | |
| col5 | varchar(1) | YES | | (null) | |
SQL from SQL can generate the drop statement using ordinal_position from information_schema.columns.
mysql test> create table test.tab (col1 char(1), col2 char(1), col3 char(1), col4 char(1), col5 char(1));
Query OK, 0 rows affected (0.01 sec)
mysql test> desc test.tab;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| col1 | char(1) | YES | | NULL | |
| col2 | char(1) | YES | | NULL | |
| col3 | char(1) | YES | | NULL | |
| col4 | char(1) | YES | | NULL | |
| col5 | char(1) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
5 rows in set (0.00 sec)
This query is generating the statement to drop the third column...
mysql test> select concat('alter table ',table_schema,'.',table_name,' drop column ',column_name,';') as query1 from information_schema.columns where table_schema='test' and table_name='tab' and ordinal_position=3;
+----------------------------------------+
| query1 |
+----------------------------------------+
| alter table test.tab drop column col3; |
+----------------------------------------+
1 row in set (0.00 sec)
Now to run the projected command...
mysql test> alter table test.tab drop column col3;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
The column definition has been removed from the table.
mysql test> desc test.tab;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| col1 | char(1) | YES | | NULL | |
| col2 | char(1) | YES | | NULL | |
| col4 | char(1) | YES | | NULL | |
| col5 | char(1) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
4 rows in set (0.01 sec)
Name them (columns in your db mirroring the spreadsheet) with the numbers/letters in full correspondence with your spreadsheet.
And then you'd be able to use regular ALTER TABLE ... DROP COLUMN.
SQL:
DELIMITER $$ CREATE TRIGGER `Activation_code` BEFORE UPDATE
ON `user_users` FOR EACH ROW
BEGIN
IF OLD.activation_code_time < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 15 MINUTE)) THEN SET NEW.activation_code = SELECT(ROUND((RAND() * (999999-100000))+100000)), NEW.activation_code_time = SELECT(UNIX_TIMESTAMP());
END
$$ DELIMITER ;
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT(ROUND((RAND() * (999999-100000))+100000)), NEW.activation_code_time = SEL' at line 4
Can anyone please tell me where is an error. and How can I resolve it?
Selects need to be bracketed, all statements need to be terminated with ; and you need an end if
DELIMITER $$
CREATE TRIGGER `Activation_code` BEFORE UPDATE
ON `user_users` FOR EACH ROW
BEGIN
IF OLD.activation_code_time < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 15 MINUTE)) THEN
SET NEW.activation_code = (SELECT(ROUND((RAND() * (999999-100000))+100000))),
NEW.activation_code_time = (SELECT(UNIX_TIMESTAMP()));
END IF;
END $$
DELIMITER ;
If there is a chance that activation_code_time may be null you should code for it.
drop trigger if exists `Activation_code`;
DELIMITER $$
create TRIGGER `Activation_code` BEFORE UPDATE
ON `users` FOR EACH ROW
BEGIN
IF coalesce(OLD.activation_code_time,0) < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 MINUTE)) THEN
SET NEW.activation_code = (SELECT(ROUND((RAND() * (999999-100000))+100000))),
NEW.activation_code_time = (SELECT(UNIX_TIMESTAMP()));
END IF;
END
$$ DELIMITER ;
mysql> describe users;
+----------------------+-------------+------+-----+---------+-------------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+-------------+------+-----+---------+-------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| uid | int(11) | YES | | NULL | |
| NAMID | varchar(20) | YES | | NULL | VIRTUAL GENERATED |
| activation_code | int(11) | YES | | NULL | |
| activation_code_time | int(11) | YES | | NULL | |
+----------------------+-------------+------+-----+---------+-------------------+
6 rows in set (0.00 sec)
mysql> select * from users;
+----+------+------+-------+-----------------+----------------------+
| id | name | uid | NAMID | activation_code | activation_code_time |
+----+------+------+-------+-----------------+----------------------+
| 1 | aaa | 1 | aaa|1 | 589392 | 1514804785 |
| 2 | bbb | 2 | bbb|2 | NULL | NULL |
+----+------+------+-------+-----------------+----------------------+
2 rows in set (0.00 sec)
mysql> select * from users;update users set name = 'aaa' where id = 1;select * from users;
+----+------+------+-------+-----------------+----------------------+
| id | name | uid | NAMID | activation_code | activation_code_time |
+----+------+------+-------+-----------------+----------------------+
| 1 | aaa | 1 | aaa|1 | 589392 | 1514804785 |
| 2 | bbb | 2 | bbb|2 | NULL | NULL |
+----+------+------+-------+-----------------+----------------------+
2 rows in set (0.00 sec)
Query OK, 1 row affected (0.05 sec)
Rows matched: 1 Changed: 1 Warnings: 0
+----+------+------+-------+-----------------+----------------------+
| id | name | uid | NAMID | activation_code | activation_code_time |
+----+------+------+-------+-----------------+----------------------+
| 1 | aaa | 1 | aaa|1 | 616615 | 1514805252 |
| 2 | bbb | 2 | bbb|2 | NULL | NULL |
+----+------+------+-------+-----------------+----------------------+
2 rows in set (0.00 sec)
I am trying to remove a column from a MySQL table that I am using with Handsontable. When I remove a column from the Handsontable, I can get the column's index using the afterRemoveCol() callback:
afterRemoveCol: function (index, amount) {
alert(index +' amount: '+amount);
}
I would like to remove the column using the column number (n) returned by this callback function from the MySQL table using something like:
ALTER TABLE tbl_Blah DROP COLUMN n;
So, if I want to drop column #3 from the MySQL table, How would I do this using just the column number?
To add to RMathis answer, you can do everything within SQL by also using SET to define the DROP string in conjuntion with PREPARE and EXECUTE
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE Table1
(`col1` varchar(1),
`col2` varchar(1),
`col3` varchar(1),
`col4` varchar(1),
`col5` varchar(1))
;
set #col = (select column_name
from information_schema.columns
where table_name='table1' and ordinal_position=3);
SET #s = CONCAT("alter table table1 drop column ", #col);
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Query 1:
desc table1
Results:
| COLUMN_NAME | COLUMN_TYPE | IS_NULLABLE | COLUMN_KEY | COLUMN_DEFAULT | EXTRA |
|-------------|-------------|-------------|------------|----------------|-------|
| col1 | varchar(1) | YES | | (null) | |
| col2 | varchar(1) | YES | | (null) | |
| col4 | varchar(1) | YES | | (null) | |
| col5 | varchar(1) | YES | | (null) | |
SQL from SQL can generate the drop statement using ordinal_position from information_schema.columns.
mysql test> create table test.tab (col1 char(1), col2 char(1), col3 char(1), col4 char(1), col5 char(1));
Query OK, 0 rows affected (0.01 sec)
mysql test> desc test.tab;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| col1 | char(1) | YES | | NULL | |
| col2 | char(1) | YES | | NULL | |
| col3 | char(1) | YES | | NULL | |
| col4 | char(1) | YES | | NULL | |
| col5 | char(1) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
5 rows in set (0.00 sec)
This query is generating the statement to drop the third column...
mysql test> select concat('alter table ',table_schema,'.',table_name,' drop column ',column_name,';') as query1 from information_schema.columns where table_schema='test' and table_name='tab' and ordinal_position=3;
+----------------------------------------+
| query1 |
+----------------------------------------+
| alter table test.tab drop column col3; |
+----------------------------------------+
1 row in set (0.00 sec)
Now to run the projected command...
mysql test> alter table test.tab drop column col3;
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
The column definition has been removed from the table.
mysql test> desc test.tab;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| col1 | char(1) | YES | | NULL | |
| col2 | char(1) | YES | | NULL | |
| col4 | char(1) | YES | | NULL | |
| col5 | char(1) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
4 rows in set (0.01 sec)
Name them (columns in your db mirroring the spreadsheet) with the numbers/letters in full correspondence with your spreadsheet.
And then you'd be able to use regular ALTER TABLE ... DROP COLUMN.
In a game for Android users can login via Google+, Facebook, Twitter:
When the app connects to the MySQL/PHP backend it sends a list of the social ids and I store them as sid column in social table:
+--------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+-------+
| sid | varchar(180) | NO | PRI | NULL | |
| given | varchar(180) | NO | | NULL | |
| family | varchar(180) | YES | | NULL | |
| city | varchar(180) | YES | | NULL | |
| photo | varchar(1000) | YES | | NULL | |
| stamp | int(11) | NO | | NULL | |
| uid | int(11) | NO | | NULL | |
+--------+---------------+------+-----+---------+-------+
In the other table called users I keep autoincremented user ids as uid column and use it to track their games and achievements (column medals):
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| uid | int(11) | NO | PRI | NULL | auto_increment |
| created | int(11) | NO | | NULL | |
| stamp | int(11) | NO | | NULL | |
| banned_until | datetime | YES | | NULL | |
| banned_reason | varchar(180) | YES | | NULL | |
| medals | int(11) | NO | | 0 | |
+---------------+--------------+------+-----+---------+----------------+
In my PHP login script I try to merge social accounts whenever possible -
by taking all received sids, finding the corresponding uids and then taking the lowest found uid and updating the records in the social table to use that lowest uid.
This works well in PHP, but now I am trying to move the merging functionality into a MySQL stored procedure with 2 prepared statements:
delimiter $$$
drop procedure if exists merge_users;
create procedure merge_users(IN in_sids varchar(255))
begin
declare sql_1 varchar(255);
declare sql_2 varchar(255);
declare out_uid varchar(255);
set sql_1 = concat('select min(uid) into out_uid from social where sid in (', in_sids, ')');
prepare sth_1 from sql_1;
execute sth_1;
deallocate prepare sth_1;
IF found_rows() > 0 THEN
set sql_2 = concat('update social set uid=', out_uid, ' where sid in (', in_sids, ')');
prepare sth_2 from sql_2;
execute sth_2;
deallocate prepare sth_2;
ELSE
insert into users(created, stamp, medals, green, red)
values (unix_timestamp(), unix_timestamp(), 0, 0, 0);
select last_insert_uid() into out_uid;
END IF;
select out_uid;
end
$$$
Unfortunately, the above code prints the syntax error message:
ERROR 1064 (42000): You have an error in your SQL syntax;
check the manual that
execute sth_1;
deallocate prepare sth_1;
IF foun' at line 8
i'm trying to write a trigger, I have following tables:
BookingRequest:
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| idRequest | int(11) | NO | PRI | NULL | auto_increment |
| roomClass | int(11) | NO | | NULL | |
| inDate | date | NO | | NULL | |
| outDate | date | NO | | NULL | |
| numOfBeds | int(11) | NO | | NULL | |
| status | int(11) | NO | MUL | NULL | |
| idUser | int(11) | NO | MUL | NULL | |
+-----------+---------+------+-----+---------+----------------+
status table:
+------------+--------------------------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------------------------------------------+------+-----+---------+-------+
| idStatus | int(11) | NO | PRI | NULL | |
| nameStatus | enum('underConsideration','approved','rejected') | YES | | NULL | |
+------------+--------------------------------------------------+------+-----+---------+-------+
OccupiedRoom:
+--------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+----------------+
| idOccupation | int(11) | NO | PRI | NULL | auto_increment |
| idRoom | int(11) | NO | | NULL | |
| idRequest | int(11) | NO | | NULL | |
+--------------+---------+------+-----+---------+----------------+
i need a trigger which will change status in BookingReques to 1 if request with the same id is inserted into OccupiedRoom table, so i tried something like this
create trigger occupy_trig after insert on OccupiedRoom
for each row
begin
if BookingRequest.idRequest= NEW.idRequest
then
update BookingRequest
set status = '1';
where idRequest = NEW.idRequest;
end if;
END;
and it doesn't work, so any suggestions would be very appriciated
Try this:
DELIMITER $$
CREATE TRIGGER occupy_trig
AFTER INSERT ON `OccupiedRoom` FOR EACH ROW
begin
DECLARE id_exists Boolean;
-- Check BookingRequest table
SELECT 1
INTO #id_exists
FROM BookingRequest
WHERE BookingRequest.idRequest= NEW.idRequest;
IF #id_exists = 1
THEN
UPDATE BookingRequest
SET status = '1'
WHERE idRequest = NEW.idRequest;
END IF;
END;
$$
DELIMITER ;
With your requirements you don't need BEGIN END and IF with unnecessary SELECT in your trigger. So you can simplify it to this
CREATE TRIGGER occupy_trig AFTER INSERT ON occupiedroom
FOR EACH ROW
UPDATE BookingRequest
SET status = 1
WHERE idRequest = NEW.idRequest;
Maybe remove the semi-colon after set because now the where statement doesn't belong to the update statement. Also the idRequest could be a problem, better write BookingRequest.idRequest
DELIMITER //
CREATE TRIGGER contacts_after_insert
AFTER INSERT
ON contacts FOR EACH ROW
BEGIN
DECLARE vUser varchar(50);
-- Find username of person performing the INSERT into table
SELECT USER() INTO vUser;
-- Insert record into audit table
INSERT INTO contacts_audit
( contact_id,
deleted_date,
deleted_by)
VALUES
( NEW.contact_id,
SYSDATE(),
vUser );
END; //
DELIMITER ;