This looks like a pretty rudimentary question but for someone who is new to MySQL, it has proven to be a tough nut to crack.
I've been trying to create a stored procedure in the MySQL and this is what I tried:
CREATE DEFINER=`root`#`localhost` PROCEDURE `test_procedure`(
IN dtst_nm varchar(42)
)
BEGIN
SELECT
COUNT(*)
FROM
data_hub.dtst_nm
;
END
When I run this, I get the error that dtst_nm doesn't exist. The exact error message is:
"Error Code: 1146. Table 'data_hub.dtst_nm' doesn't exist"
Clearly the variable is not getting resolved.
From what I gathered, the syntax seems to be right. What am I missing?
This is a Dynamic SQL problem. You cannot directly specify variables in place of table and column names. You will need to use string functions of create SQL query string. Then use Prepare with Execute to run the query.
Try:
DELIMITER $$
DROP PROCEDURE IF EXISTS `test_procedure` $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `test_procedure`(
IN `dtst_nm` varchar(42)
)
BEGIN
SET #s = CONCAT('SELECT COUNT(*) FROM ', dtst_nm );
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
Related
I want to have a MySQL procedure, that makes SELECT FROM table and return the result in JSON format via JSON_ARRAYAGG, but the table name to be a parameter.
So there is my solution, but it doesn't work when I call it, because the system thinks the parameter is table name. I will be very thankful if someone can help me.
CREATE DEFINER=`ME` PROCEDURE `main_list`(
IN `the_table` CHAR(50)
)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
BEGIN
SELECT JSON_ARRAYAGG(JSON_OBJECT('id', id,'name', NAME)) from the_table;
END
The call and error:
CALL `main_list`('martin');
/* SQL Error (1146): Table 'my_server.the_table' doesn't exist */
As Akina and gotgn already said you can't use tablename in that way and in some other ise PREPARE Statetemnts for it
DELIMITER //
CREATE PROCEDURE `main_list`(
IN `the_table` CHAR(50)
)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
BEGIN
SET #sql := CONCAT("SELECT JSON_ARRAYAGG(JSON_OBJECT('id', id,'name', NAME)) FROM ",the_table);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END//
DELIMITER ;
delimiter //
DROP PROCEDURE IF EXISTS drop_table//
create procedure drop_table(in table_name varchar) #创建带参数的存储过程
begin
drop table if EXISTS table_name;
end//
delimiter ;
call drop_table('a')
i use Navicat to create a procedure to drop a parameter table in mysql.
Error:Invalid Stored Procedure Syntax
As commented by P.Salmon, you cannot pass substitute the procedure argument (ie a variable) directly in a sql statement. You need dynamic sql: build the query as a string, then execute it.
delimiter //
create procedure drop_table(in p_table_name varchar(200))
begin
set #q = concat('drop table if exists ', p_table_name);
prepare stmt from #q;
execute stmt;
deallocate prepare stmt;
end//
delimiter ;
Demo on DB Fiddle
Note: the varchar datatype needs a length.
I am new to MySQl stored procedure. I am trying to create a simple procedure with single IN parameter with execution of simple prepare select statement. Am using IN parameter directly in select statement while creating PREPARE, this throwing Unknown column error for IN parameter on executing prepare statement.
DELIMITER $$
DROP PROCEDURE IF EXISTS test_prep_stmt_two$$
CREATE PROCEDURE test_prep_stmt_two(IN user_id_in INT)
BEGIN
#this line causing error
PREPARE param_stmt FROM "select * from users u where u.user_id=user_id_in";
EXECUTE param_stmt;
DEALLOCATE PREPARE param_stmt;
END $$
DELIMITER ;
DELIMITER $$
when I call procedure like CALL test_prep_stmt_two(1); am getting below error.
Error Code: 1054
Unknown column 'user_id_in' in 'where clause'
But if I set IN param value to any variable inside procedure and use that in prepare select statement then it's working fine. Below procedure is working fine.
DELIMITER $$
DROP PROCEDURE IF EXISTS test_prep_stmt_three$$
CREATE PROCEDURE test_prep_stmt_three(IN user_id_in INT)
BEGIN
SET #user_id_in=user_id_in;
#this works fine
PREPARE set_stmt FROM "select * from users u where u.user_id=#user_id_in";
EXECUTE set_stmt;
DEALLOCATE PREPARE set_stmt;
END $$
DELIMITER ;
Please, can anyone explain me why using IN parameter in prepare select statement throwing error.
DELIMITER $$
DROP PROCEDURE IF EXISTS test_prep_stmt_two$$
CREATE PROCEDURE test_prep_stmt_two(IN user_id_in INT)
BEGIN
SET #t1 = CONCAT("SELECT * FROM users u WHERE u.user_id = '", user_id_in, "'");
PREPARE param_stmt FROM #t1;
EXECUTE param_stmt;
DEALLOCATE PREPARE param_stmt;
END $$
DELIMITER ;
Try the above code. Hope this will help.
I'm creating a sql script for a migration functionality of ours. We want to migrate data from one magento-instance to another (using pure SQL because the import/export of magento is pretty limited).
One of the challenges ist that I want to dynamically alter the AUTO_INCREMENT value of a table so it doesn't need to be done manually in multiple steps. I want to set the AUTO_INCREMENT value to the current-maximum value of the corresponding column + 1.
I prepared the following stored procedure for this:
DELIMITER $$
CREATE PROCEDURE alter_auto_inc_customer()
BEGIN
SELECT #max := MAX(entity_id)+ 1 FROM customer_entity;
PREPARE stmt FROM 'ALTER TABLE customer_entity AUTO_INCREMENT = ?';
EXECUTE stmt USING #max;
END $$
This command runs smoothly. Afterwards the procedure should just be called by a simple statement:
CALL alter_auto_inc_customer();
When I execute the "call"-statement, I get a 1064 Syntax error. It's probably trivial but I can't figure it out for the life of me...
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1
Does anyone have an idea what the issue is?
I need to get this into one or more stored procedures because I need to be able to run similar statements for multiple tables in the database.
Instead of altering the table structure you can use a trigger to get the max value + 1 before insert data:
DELIMITER $$
DROP TRIGGER IF EXISTS custom_autoincrement_bi$$
CREATE TRIGGER custom_autoincrement_bi BEFORE INSERT ON customer_entity
FOR each ROW
BEGIN
SET NEW.entity_id = select max(entity_id) + 1 from customer_entity;
END$$
DELIMITER ;
But if you want to alter the table from stored procedure
DELIMITER $$
CREATE PROCEDURE alter_auto_inc_customer()
BEGIN
SELECT MAX(entity_id) + 1 into #max FROM customer_entity;
set #sql = concat('ALTER TABLE customer_entity AUTO_INCREMENT = ', #max);
PREPARE stmt FROM #sql;
EXECUTE stmt ;
DEALLOCATE PREPARE stmt;
END $$
Hello dearest community,
EDITED
This is my solution, based on Devart answer. I slightly modify the procedure parameter and also fix some % things..
DELIMITER $$
DROP PROCEDURE IF EXISTS `cosmedicdb`.`proc_searchall` $$
CREATE PROCEDURE `cosmedicdb`.`proc_searchall` (output TEXT, tbl varchar(50), kolom_kriteria VARCHAR(20),
kolom_nilai VARCHAR(20))
BEGIN
SET #query = CONCAT('SELECT ', output, ' FROM ',tbl,' WHERE ', kolom_kriteria, ' LIKE CONCAT(','\'%',kolom_nilai, '%\')');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
I think one can enhance this to support search of numeric value field
Original Question below
First of all, I hope this is not a repost question.
I want to create a flexible search procedure. That is, the column ad the value of the column to be search, can be supplied from the argument itself. Currently this is my search procedure looks like :
DELIMITER $$
DROP PROCEDURE IF EXISTS `cosmedicdb`.`proc_searchtindakan` $$
CREATE PROCEDURE `cosmedicdb`.`proc_searchtindakan` (kolom VARCHAR(20),
kolomnilai VARCHAR(20))
BEGIN
CASE kolom
WHEN 'jenis'
THEN
SELECT jenis, harga
FROM cosmedicdb.tb_mastertindakan
where jenis like concat('%',kolomnilai,'%');
END CASE;
END $$
DELIMITER ;
You can see that this procedure only work for certain column to be search. Is it possible (and safe) to create just one search procedure that allows me to search using any column as the defining search criteria?
Thanks
You can do it with a prepared statements: build a query and execute it, e.g. -
DELIMITER $$
CREATE PROCEDURE proc_searchtindakan(IN kolom VARCHAR(20), IN kolomnilai VARCHAR(20))
BEGIN
SET #query = CONCAT('SELECT ', kolom, 'FROM cosmedicdb.tb_mastertindakan WHERE ', kolom, ' LIKE CONCAT(\'%\'', kolomnilai, '\'%\'');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;
...in example I have removed 'harga' field from the list of fields; add it if you need.