List of Stored Procedures/Functions Mysql Command Line - mysql

How can I see the list of the stored procedures or stored functions in mysql command line like show tables; or show databases; commands.

SHOW PROCEDURE STATUS;
SHOW FUNCTION STATUS;

show procedure status
will show you the stored procedures.
show create procedure MY_PROC
will show you the definition of a procedure. And
help show
will show you all the available options for the show command.

For view procedure in name wise
select name from mysql.proc
below code used to list all the procedure and below code is give same result as show procedure status
select * from mysql.proc

A more specific way:
SHOW PROCEDURE STATUS
WHERE Db = DATABASE() AND Type = 'PROCEDURE'

As mentioned above,
show procedure status;
Will indeed show a list of procedures, but shows all of them, server-wide.
If you want to see just the ones in a single database, try this:
SHOW PROCEDURE STATUS WHERE Db = 'databasename';

Alternative:
SELECT * FROM INFORMATION_SCHEMA.ROUTINES

My preference is for something that:
Lists both functions and procedures,
Lets me know which are which,
Gives the procedures' names and types and nothing else,
Filters results by the current database, not the current definer
Sorts the result
Stitching together from other answers in this thread, I end up with
select
name, type
from
mysql.proc
where
db = database()
order by
type, name;
... which ends you up with results that look like this:
mysql> select name, type from mysql.proc where db = database() order by type, name;
+------------------------------+-----------+
| name | type |
+------------------------------+-----------+
| get_oldest_to_scan | FUNCTION |
| get_language_prevalence | PROCEDURE |
| get_top_repos_by_user | PROCEDURE |
| get_user_language_prevalence | PROCEDURE |
+------------------------------+-----------+
4 rows in set (0.30 sec)

Shows all the stored procedures:
SHOW PROCEDURE STATUS;
Shows all the functions:
SHOW FUNCTION STATUS;
Shows the definition of the specified procedure:
SHOW CREATE PROCEDURE [PROC_NAME];
Shows you all the procedures of the given database:
SHOW PROCEDURE STATUS WHERE Db = '[db_name]';

use this:
SHOW PROCEDURE STATUS;

SELECT specific_name FROM `information_schema`.`ROUTINES` WHERE routine_schema='database_name'

A variation on Praveenkumar_V's post:
SELECT `name` FROM mysql.proc WHERE db = 'dbname' AND `type` = 'PROCEDURE';
SELECT `name` FROM mysql.proc WHERE db = 'dbname' AND `type` = 'FUNCTION';
..and this because I needed to save time after some housekeeping:
SELECT CONCAT(
"GRANT EXECUTE ON PROCEDURE `"
,`name`
,"` TO username#'%'; -- "
,`comment`
)
FROM mysql.proc
WHERE db = 'dbname'
AND `type` = 'PROCEDURE';
SELECT CONCAT(
"GRANT EXECUTE ON FUNCTION `"
,`name`
,"` TO username#'%'; -- "
,`comment`
)
FROM mysql.proc
WHERE db = 'dbname'
AND `type` = 'FUNCTION';

To show just yours:
SELECT
db, type, specific_name, param_list, returns
FROM
mysql.proc
WHERE
definer LIKE
CONCAT('%', CONCAT((SUBSTRING_INDEX((SELECT user()), '#', 1)), '%'));

If you want to list Store Procedure for Current Selected Database,
SHOW PROCEDURE STATUS WHERE Db = DATABASE();
it will list Routines based on current selected Database
UPDATED
to list out functions in your database
select * from information_schema.ROUTINES where ROUTINE_SCHEMA="YOUR DATABASE NAME" and ROUTINE_TYPE="FUNCTION";
to list out routines/store procedures in your database,
select * from information_schema.ROUTINES where ROUTINE_SCHEMA="YOUR DATABASE NAME" and ROUTINE_TYPE="PROCEDURE";
to list tables in your database,
select * from information_schema.TABLES WHERE TABLE_TYPE="BASE TABLE" AND TABLE_SCHEMA="YOUR DATABASE NAME";
to list views in your database,
method 1:
select * from information_schema.TABLES WHERE TABLE_TYPE="VIEW" AND TABLE_SCHEMA="YOUR DATABASE NAME";
method 2:
select * from information_schema.VIEWS WHERE TABLE_SCHEMA="YOUR DATABASE NAME";

As of MySQL 8.0, the mysql.procs table has been removed. Running any of the commands from answers here that use this table will yield you an error that says (quite logically):
Table 'mysql.proc' doesn't exist
Instead, to retrieve a list of only the names of procedures/functions, use:
SELECT specific_name FROM `information_schema`.`ROUTINES` WHERE routine_schema='<your_db_name>';
In my case, I edited it to show only the procedures and not the functions:
SELECT specific_name FROM `information_schema`.`ROUTINES` WHERE routine_schema='<your_db_name>' AND routine_type='PROCEDURE';

My favorite rendering of the procedures list of the current database: name, parameters list, comment
SELECT specific_name AS name, param_list AS params, `comment`
FROM mysql.proc
WHERE db = DATABASE()
AND type = 'PROCEDURE';
Add returns for functions:
SELECT specific_name AS name, param_list AS params, `returns`, `comment`
FROM mysql.proc
WHERE db = DATABASE()
AND type = 'FUNCTION';

show procedure status;
using this command you can see the all procedures in databases

List user's procedures and functions for all databases:
SELECT
`ROUTINE_SCHEMA` AS `database`
,`ROUTINE_TYPE` AS `type`
,`SPECIFIC_NAME` AS `name`
,`DTD_IDENTIFIER` AS `data_type`
FROM
`INFORMATION_SCHEMA`.`ROUTINES`
WHERE
`definer` LIKE
CONCAT('%', CONCAT((SUBSTRING_INDEX((SELECT user()), '#', 1)), '%'))
ORDER BY
`database`
,`type`
,`name`
;
List user's procedures and functions for the database in use:
SELECT
`ROUTINE_SCHEMA` AS `database`
,`ROUTINE_TYPE` AS `type`
,`SPECIFIC_NAME` AS `name`
,`DTD_IDENTIFIER` AS `data_type`
FROM
`INFORMATION_SCHEMA`.`ROUTINES`
WHERE
`definer` LIKE
CONCAT('%', CONCAT((SUBSTRING_INDEX((SELECT user()), '#', 1)), '%'))
AND
`ROUTINE_SCHEMA` = DATABASE()
ORDER BY
`type`
,`name`
;

Use the following query for all the procedures:
select * from sysobjects
where type='p'
order by crdate desc

Related

MySQL turn a JOIN statement into a Stored Procedure or Function?

So I have a JOIN statement that I will be using in multiple places. It essentially finds an IP address and matches it to said location from the intermediate table. I need to pass in two variables - one being the prefix of my database/schema and the other being the IP Address itself.
Therefore used is the CONCAT() function in order to piece it together.
So at the moment I have a procedure that looks something like this:
CREATE DEFINER=`root`#`%` PROCEDURE `LocationFromIp`(
ipAddress VARCHAR(16),
clientComp VARCHAR(32)
)
BEGIN
DECLARE test VARCHAR(255);
SET #networkSql = CONCAT("
SET #Location =
(SELECT `network`.`Name`
FROM `", clientComp, "-settings`.`iptable` AS `iptable`
LEFT JOIN `", clientComp, "-settings`.`network` AS `network`
ON `network`.`Subnet` = `iptable`.`Subnet`
WHERE `iptable`.`IP` = '", ipAddress, "'
LIMIT 1);
");
PREPARE test1 FROM #networkSql;
EXECUTE test1;
SELECT #Location AS `Location`;
It returns the result I want however I don't know how I can use this in a statement.
SELECT `IPAddress` AS CALL LocationFromIp('clientComp', `IPAddress`)
(
SELECT `IPAddress`
FROM `clientComp-data`.`tablename`
WHERE #date > `Date`;
)
GROUP BY `IPAddress`
The above does not work but I hope you can understand my thinking!
So how would I do it?
Why can't you adjust your stored procedure to include all the fields that you need from the very beginning?

MySQL create view across all prefixed databases' table

I have databases named company_abc, company_xyz, etc. Those company_* databases have all the same structure and they contain users table.
What I need to do is to aggregate all users data from just company_* databases and replicate this view to another server. The view would just be something like
COMPANY NAME | USERNAME
abc | user#email.com
abc | user1#email.com
xyz | user2#email.com
company3 | user3#email.com
Is something like that possible in MySQL?
The databases are created dynamically, as well as the users so I can't create a view with just a static set of databases.
As you say you want to create view with dynamic database names - so the result you want to achieve is not possible in current versions of mysql.
So you have example following options:
Option 1
If you want to get result of all databases users tables you could define a stored procedure that uses prepared statement. This procedure needs parameter db_prefix what in your case is company_%. Basicly this procedure selects all tables named as users from information_schema when database name is like db_prefix parameter value. After that it loops through results and creates query string as union all users tables and executes this query. When creating a query string i also add field called source, so i can identify from what database this result is coming. In my example my databases are all in default collation utf8_unicode_ci.
In this case you can define procedure example "getAllUsers"
-- Dumping structure for procedure company_abc1.getAllUsers
DELIMITER //
CREATE DEFINER=`root`#`localhost` PROCEDURE `getAllUsers`(IN `db_prefix` TEXT)
DETERMINISTIC
COMMENT 'test'
BEGIN
DECLARE qStr TEXT DEFAULT '';
DECLARE cursor_VAL VARCHAR(255) DEFAULT '';
DECLARE done INTEGER DEFAULT 0;
DECLARE cursor_i CURSOR FOR SELECT DISTINCT (table_schema) FROM information_schema.tables WHERE table_name = 'users' AND table_schema LIKE db_prefix COLLATE utf8_unicode_ci;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cursor_i;
read_loop: LOOP
FETCH cursor_i INTO cursor_VAL;
IF done = 1 THEN
LEAVE read_loop;
END IF;
IF qStr != '' THEN
SET qStr = CONCAT(qStr, ' UNION ALL ');
END IF;
SET qStr = CONCAT(qStr, ' SELECT *, \'', cursor_VAL ,'\' as source FROM ', cursor_VAL, '.users');
END LOOP;
CLOSE cursor_i;
SET #qStr = qStr;
PREPARE stmt FROM #qStr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #qStr = NULL;
END//
DELIMITER ;
Now you can get your all users result as:
CALL getAllUsers('company_%');
In my example database it results as:
id name source
1 User 1 company_abc1
2 User 2 company_abc1
3 User 3 company_abc1
1 User 1 company_abc2
2 User 2 company_abc2
3 User 3 company_abc2
1 User 1 company_abc3
2 User 2 company_abc3
3 User 3 company_abc3
1 User 1 company_abc4
2 User 2 company_abc4
3 User 3 company_abc4
1 User 1 company_abc5
2 User 2 company_abc5
3 User 3 company_abc5
Option 2
If you really, really need view then you can modify first procedure and instead of executeing select you can create view. Example like this:
-- Dumping structure for procedure company_abc1.createAllUsersView
DELIMITER //
CREATE DEFINER=`root`#`localhost` PROCEDURE `createAllUsersView`(IN `db_prefix` TEXT)
DETERMINISTIC
COMMENT 'test'
BEGIN
DECLARE qStr TEXT DEFAULT '';
DECLARE cursor_VAL VARCHAR(255) DEFAULT '';
DECLARE done INTEGER DEFAULT 0;
DECLARE cursor_i CURSOR FOR SELECT DISTINCT (table_schema) FROM information_schema.tables WHERE table_name = 'users' AND table_schema LIKE db_prefix COLLATE utf8_unicode_ci;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cursor_i;
read_loop: LOOP
FETCH cursor_i INTO cursor_VAL;
IF done = 1 THEN
LEAVE read_loop;
END IF;
IF qStr != '' THEN
SET qStr = CONCAT(qStr, ' UNION ALL ');
END IF;
SET qStr = CONCAT(qStr, ' SELECT *, \'', cursor_VAL ,'\' as source FROM ', cursor_VAL, '.users');
END LOOP;
CLOSE cursor_i;
SET #qStr = CONCAT('CREATE OR REPLACE VIEW allUsersView AS ', qStr);
PREPARE stmt FROM #qStr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #qStr = NULL;
END//
DELIMITER ;
In this stored procedure we create/replace view called allUsersView, so basicly every time you will execute this procedure it will updates view.
In my test case it creates view like this:
CREATE OR REPLACE VIEW `allusersview` AS
SELECT *, 'company_abc1' as source FROM company_abc1.users
UNION ALL SELECT *, 'company_abc2' as source FROM company_abc2.users
UNION ALL SELECT *, 'company_abc3' as source FROM company_abc3.users
UNION ALL SELECT *, 'company_abc4' as source FROM company_abc4.users
UNION ALL SELECT *, 'company_abc5' as source FROM company_abc5.users ;
And now you can use view.
SELECT * FROM allusersview
And result is same as in first option.
All tested on:
Mysql 5.6.16
To find the list of database names:
SELECT SCHEMA_NAME
FROM information_schema.`SCHEMATA`
WHERE SCHEMA_NAME LIKE 'company%';
If you can code in something like PHP, the rest is pretty easy -- build a UNION of SELECTs from each database. But, if you must do it just in SQL...
To build the UNION, write a Stored Procedure. It will do the above query in a CURSOR. Inside the loop that walks through the cursor, CONCAT() a constructed SELECT onto a UNION you are building.
When the loop is finished, PREPARE and EXECUTE the constructed UNION. That will deliver something like the output example you had.
But, if you now need to INSERT the results of that into another server, you should leave the confines of the Stored Procedure and use some other language.
OK, OK, if you must stay in SQL, then you need some setup: Create a "Federated" table that connects to the other server. Now, in your SP, concatenate INSERT INTO fed_tbl in front of the UNION. Then the execute should do the entire task.
If you have trouble with the FEDERATED Engine, you may need to switch to FederatedX in MariaDB.
"The details are left as an exercise to the reader."
I already marked this as duplicate of Mysql union from multiple database tables
(SELECT *, 'abc' as COMPANY_NAME from company_abc.users)
union
(SELECT *, 'xyz' as COMPANY_NAME from company_xyz.users)
union
(SELECT *, 'company3' as COMPANY_NAME from company_company3.users)
...
I think that the only method to make this is to write a stored procedure that read all database and table name from information_schema.table, build a string with union select * from company_abc.users union all select * from company_xyz and then execute the command with prepared statement: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html

Run a query foreach databases (mysql)

I'm looking for a straight way to run a query on all databases hosted on my mysql server.
I have a bunch of Magento installations and I want to truncate all Magento log table on all databases:
log_customer
log_visitor
log_visitor_info
log_url
log_url_info
log_quote
report_viewed_product_index
report_compared_product_index
report_event
catalog_compare_item
I think it something very easy to accomplish in mysql but I cannot find a straight answer/solution.
*UPDATE *
According to #Ollie Jones it is not possible to do it without a STORE PROCEDURE or a server side language ( PHP or whatever )
UPDATE 1
I choose to follow the PHP approach (#samitha) for 2 reasons:
STORE PROCEDURE looks more complicated
Query on 'information_schema' table is very slow ( at least if you have many DB/TABLES)
SELECT DISTINCT SCHEMA_NAME AS `database`
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql')
ORDER BY SCHEMA_NAME
gets you a list of all the non-MYSQL databases on your system.
SELECT TABLE_SCHEMA AS `database`,
TABLE_NAME AS `table`
FROM information_schema.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_SCHEMA, TABLE_NAME
gets you a list of all the actual tables (excluding SYSTEM VIEWs like the TABLES table, and user-defined views) in all the databases.
Then, you should implement logic in your program to ensure that, for each database, it really is a Magento database before you truncate certain tables. Otherwise, you might become a despised person among your co-workers. :-)
Edit
Here's a stored procedure.
You need to edit it to do exactly what you need it to do; in particular, it counts rows rather than truncating tables, and it doesn't contain the correct list of log tables. (It would be irresponsible for me to publish such a wildly destructive stored procedure; you should edit it yourself to do the destructive part.)
DELIMITER $$
DROP PROCEDURE IF EXISTS `zap_magento_logs`$$
CREATE PROCEDURE `zap_magento_logs`()
BEGIN
-- declare variables for database and table names
DECLARE dbname VARCHAR(128) DEFAULT '';
DECLARE tbname VARCHAR(128) DEFAULT '';
DECLARE done INTEGER DEFAULT 0;
-- declare cursor for list of log tables
DECLARE log_table_list CURSOR FOR
SELECT TABLE_SCHEMA AS `database`,
TABLE_NAME AS `table`
FROM `information_schema`.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME IN
(
'log_customer',
'log_visitor',
'log_visitor_info',
'log_url',
'log_url_info',
'log_quote'
)
ORDER BY TABLE_SCHEMA, TABLE_NAME;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET done = 1;
OPEN log_table_list;
log_table: LOOP
FETCH log_table_list INTO dbname, tbname;
IF done = 1 THEN
LEAVE log_table;
END IF;
-- create an appropriate text string for a DDL or other SQL statement
SET #s = CONCAT('SELECT COUNT(*) AS num FROM ',dbname,'.',tbname);
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP log_table;
CLOSE log_table_list;
END$$
DELIMITER ;
You run this by issuing the SQL command
CALL zap_magento_logs();
A PHP approach would be:
$tables = array(
'log_customer',
'log_visitor',
'log_visitor_info',
'log_url',
'log_url_info',
'log_quote',
'report_viewed_product_index',
'report_compared_product_index',
'report_event',
'catalog_compare_item',
);
$dbh = new PDO('mysql:host=localhost;', 'USERNAME', 'PASSWORD', array(
PDO::ATTR_PERSISTENT => true
));
$sql = $dbh->query('SHOW DATABASES');
$getAllDbs = $sql->fetchALL(PDO::FETCH_ASSOC);
foreach ($getAllDbs as $DB) {
foreach ($tables as $table) {
$dbh->query('TRUNCATE TABLE ' . $DB['Database'] . '.' . $table);
};
};
I didn't feel like writing code to solve this so I found a different solution. I wrote SQL that generates the SQL that I need. So I saved the following to a file called createSomeSQL.sql:
SET sql_mode='PIPES_AS_CONCAT';
select
'truncate table ' || dbs.database || '.someLogTable;'
as ''
from (SELECT DISTINCT SCHEMA_NAME AS `database`
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql', 'test')
ORDER BY SCHEMA_NAME) as dbs;
You could replace the SQL in line 4 with anything you want. Then I ran this command to generate the SQL that I need:
mysql -u root -p < createSomeSQL.sql > sqlToExecute.sql
Replace "root" with your username, of course. Now the file sqlToExecute.sql contains a script you can run to execute that SQL against all your databases.
Try the following (very basic, no error handling, may not work at all, I've not tested this):
$db = mysqli_connect(); // your database connection
$tables = ["log_customer", "log_visitor", "log_visitor_info"]; // array with all the tables
foreach ($tables as $table) {
mysqli_query($db, "TRUNCATE TABLE `".$table."`"); // executes query for each element in the array
}

MySQL Derterministic migration script

I am currently looking a way to have my database under version control. To achieve so, I wanted to have deterministic procedures that can only be run only once (with corresponding undo).
I have a problem building my first script which is riddled with small bugs.
Here are the 3 main parts :
Condition to execute query (if field doesn't exists)
SELECT *
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'my_database'
AND TABLE_NAME = 'my_table'
AND COLUMN_NAME = 'full_name'
The table alteration:
ALTER TABLE
my_table
ADD full_name VARCHAR(255) NOT NULL;
And finally the data migration
UPDATE candidat dest JOIN candidat src ON dest.id = src.id
SET dest.full_name = CONCAT(src.first_name, ' ', IF(src.middle_name='', '', CONCAT(src.middle_name, ' ')), src.last_name);
I'am trying to make this work in this form:
DELIMITER $$
DROP PROCEDURE IF EXISTS migration_001;
CREATE PROCEDURE migration_001()
BEGIN
IF NOT EXISTS (
SELECT *
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'my_database'
AND TABLE_NAME = 'my_table'
AND COLUMN_NAME = 'full_name')
THEN
ALTER TABLE
my_table
ADD full_name VARCHAR(255) NOT NULL;
UPDATE candidat dest JOIN candidat src ON dest.id = src.id
SET dest.full_name = CONCAT(src.first_name, ' ', IF(src.middle_name='', '', CONCAT(src.middle_name, ' ')), src.last_name);
END IF
END;
$$
Current error I am getting:
1064 : ... right syntax to use near 'CREATE PROCEDURE migration_001() BEGIN IF NOT EXISTS ( SELECT * ' at line 3
Can anyone point me in the right direction for solving this?
BTW I am using 5.5.16-log - MySQL Community Server.
Change the order of
DELIMITER $$
and
DROP PROCEDURE IF EXISTS migration_001;
Currently you are using the wrong delimiter to drop the procedure.

How to delete all views from MySQL database using MySQL query/command?

I need to delete all views from my MySQL database. How can I do that using query?
Can anyone can help me please?
I've been using this one:
/* DROP ALL VIEWS */
SET #views = NULL;
SELECT GROUP_CONCAT(table_schema, '.', table_name) INTO #views
FROM information_schema.views
WHERE table_schema = #database_name; -- Your DB name here
SET #views = IFNULL(CONCAT('DROP VIEW ', #views), 'SELECT "No Views"');
PREPARE stmt FROM #views;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Quoting from MySQL Reference Manual:
DROP VIEW [IF EXISTS]
view_name [, view_name] ...
[RESTRICT | CASCADE]
DROP VIEW removes one or more views. You must have the DROP privilege for each view. If any of the views named in the argument list do not exist, MySQL returns an error indicating by name which non-existing views it was unable to drop, but it also drops all of the views in the list that do exist.
The IF EXISTS clause prevents an error from occurring for views that don't exist. When this clause is given, a NOTE is generated for each nonexistent view. See Section 12.7.5.41, “SHOW WARNINGS Syntax”.
RESTRICT and CASCADE, if given, are parsed and ignored.
try this untested code
DECLARE VIEW_NAME VARCHAR(31);
DECLARE VIEW_NAMES CURSOR
FOR
SELECT table_name
FROM information_schema.views;
WHERE table_schema = 'DB_Name'
OPEN VIEW_NAMES;
REPEAT
FETCH VIEW_NAMES INTO VIEW_NAME;
DROP VIEW VIEW_NAME
UNTIL done END REPEAT;
CLOSE VIEW_NAMES;
END;
Here's a Ruby method that will do what you want:
# #param [Array] databases, e.g. ['db1', 'db2']
def drop_all_views(databases)
views = ActiveRecord::Base.connection.execute("SELECT CONCAT(TABLE_SCHEMA,'.',TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_TYPE = 'VIEW' AND TABLE_SCHEMA IN('#{databases.join("', '")}');")
views = views.to_a.flatten
# Then drop all of those views from their respective databases
views.each do |v|
ActiveRecord::Base.connection.execute("DROP VIEW IF EXISTS #{v};")
end
end