Summary: Can DELETE from mysql.proc be used safely from MySQL 5.7 onward?
In question Drop all stored procedures in MySQL or using temporary stored procedures, it was mentioned that in MySQL it is not possible to use DROP PROCEDURE inside a stored procedure (mysql error code 1357, "Can't drop or alter a %s from within another stored routine").
Empirically:
DELETE from mysql.proc WHERE db = <db-name> AND name LIKE '<procedure-prefix>%';
does seem to work fine instead.
In a comment, the question was asked (but not answered):
Is mysql.proc still a viable method of interacting with MySQL meta information in 5.7?
Even though I fully realise it is not "desirable", is it "OK" to use this in MySQL 5.7? Or, is there some vital stuff which DROP PROCEDURE does, such that I must not use this workaround?
The direct delete from the procs table does not seem to take an immediate effect in the current MySQL session.
The flush statement is used in MySQL to make the server reload stuff (changing the privileges directly via update / delete and the flush privileges is probably the best analogy). However, I could not find any versions of flush that would affect the stored procs based on the documentation. So, I do not think there is any way to make the deletion of the stored proc final in the current MySQL session.
The real danger with your direct deletion approach is that it relies on an undocumented feature of MySQL. This feature may change without any notice in a future version of MySQL, making an upgrade impossible. Also, without actually debugging MySQL itself, it is very difficult to say if your approach has any unintended side effects.
For these reasons, I would not recommend to use this approach in a production code. If it is a one-off exercise, then you may get away with it.
Related
I am very new to mysql and I have I a situation where I need to update all my stored procedure in all my database. for example I have 10 database just say:
client_1,client_2,client_3,.....client_10.
Every database have same stored procedure just say:
proc_1,proc_2,proc_3,proc_4.
So if I made any changes to one of my stored procedure then it should get updated in all other database So that I don't have to do it manually.
I know the similar question have been asked but I am looking for some different approach. So what I want is some kind of mysql query or something like that in which we will pass the name of the database like:
client_1, client_3, client_8
and changes will only made to this databases.
I am using heidiSql- 10.2 with MySQL 5.6.
Thanks.
I am not entirely sure what you are wanting to do but I think you want something like this. First save the definition of your stored procedure to a file. Make sure it doesn't contain an schema references like client1.tableA. You want it to be able to run in any copy of your schema correctly. Be sure to follow the syntax rules defined by MySQL
Defining Stored Programs
Then once the stored procedure is saved you can use the mysql command line to run it for each client you want to update.
You would first connect to the database server using the mysql command line. Then issue a USE command to activate the first client database. Then run the script using the SOURCE command. See MySQL Batch Commands Then repeat for each client.
USE client1;
source c:\temp\storedProcedure.sql
USE client2;
source c:\temp\storedProcedure.sql
If this is not exactly what you needed hopefully it gives you some ideas to get you what you need.
Note that you could do the connection to the database and execute these commands via batch file instead of manually if you wanted to.
There are no statements in MySQL that create/drop/alter multiple procedures at once. You can only change one procedure at a time.
You can write an SQL script that includes a series of statements. But it's up to you to write that script.
You may write some script in Python (or other favorite language) that outputs the SQL script.
I don't know HeidiSQL, but I doubt it has any facility to apply the same change to many procedures. Nor does any other MySQL client that I'm aware of.
DB was designed for SQL Server initially. Back then all table names were mixed case. For example, UserTasks.
Hundreds of stored procedures were written on these tables and those stored procedures use mixed case table names.
DB was migrated to MySQL (on Windows) and during that process table names were automatically converted to all lower case but code inside stored procedures was converted to MySQL format without changing the table name cases.
We just migrated to Ubuntu and everything stopped working because MySQL can no longer find those tables used in SQL statements in stored procedures.
Is there a easy way around this? I know the hard way. Open each one of those 550 stored procedures and change table names to lower case one by one.
You should read https://dev.mysql.com/doc/refman/5.7/en/identifier-case-sensitivity.html
Case sensitivity of table names is a complex story on MySQL, because it works on all types of environments: Windows, which is case-insensitive, Unix and Linux, which is case-sensitive, and also MacOS which is sort of a hybrid.
You might be able to use the lower_case_table_names option. I can't be sure, because I don't use that option myself, I don't use Windows, and I seldom use MySQL stored procedures, so I'm not sure how this will interact with the procedure code.
Good luck!
I created a stored procedure, 'myProc', in a MySQL database.
Then I dropped this procedure.
I wanna create again a procedure with the same name to the before.
I create the procedure again and name it 'myProc'.
CALL myProc();
But, when I execute this procedure, it is an error like that "PROCEDURE myProc does not exit".
Also code is same to the before one.
Unable to call a stored procedure in MySQL
You've created a procedure in MySQL 5. You've granted EXECUTE privileges to your application's user account. But when your application prepares a statement to call that procedure, an exception is thrown. Perhaps it's a NullPointerException deep inside of ConnectorJ. Perhaps the exception claims that the procedure does not exist. Or perhaps you've gotten lucky enough to get the exception that leads you down the right path(Driver requires declaration of procedure to either contain a ''\nbegin'' or ''\n'' to follow argument declaration, or SELECT privilege on mysql.proc to parse column types). Here are the troubleshooting steps that I've gleaned from hours of searching the MySQL forums.
First, open two console windows. In one, log into MySQL as the application user. In the other, log in as root. In your app window, list the databases.
SHOW DATABASES;
If your application's database does not appear, then you should go to your root window and grant database privileges.
USE mydatabase;
GRANT ALL ON mydatabase TO appuser;
Now go back to the app window. List the databases again to ensure that it appears. Now that it does, go into it.
USE mydatabase;
Once you're in, try to view the procedure.
SHOW CREATE PROCEDURE myproc /G
One of three things will happen. If you get a message saying "PROCEDURE myproc does not exist" then the app user does not have privileges for it. Go back to the root window and grant them.
GRANT EXECUTE ON PROCEDURE myproc TO appuser;
The second thing that might happen is that the procedure will be found, but the body will not be listed. Instead, it will say "Create Procedure: NULL". If so, go back to the root window and take care of that.
GRANT SELECT ON mysql.proc TO appuser;
The third thing that could happen is what you want to happen; the body of the procedure will be listed. Now you should be able to call the procedure from your application.
Warnings
You may be tempted to take a couple of short-cuts to resolve problems like these. Please don't. Shortcuts may cause bigger problems down the road.
The first thing you might try is to use the root account from within your application. This is extremely dangerous. Security comes in layers. While you should use stored procedures and prepared statements to avoid SQL injection attacks, you should also apply the principle of least privilege just in case they occur anyway. Allowing your application to connect as root gives an attacker access to your most valuable resource: your data. But giving each part of the application a separate account with only the privilege that it requires quarantines the bad guy.
The second thing that you might try after hours of research is to set the "noAccessToProcedureBodies" flag in the ConnectorJ connection string. Please avoid this flag, as it circumvents the parameter type checking that the JDBC driver provides for you. This flag causes ConnectorJ to convert all of the parameters to strings, which MySQL will then convert back to the required type.
But by walking through the problem step-by-step, these short-cuts should not be necessary.
Reference
http://adventuresinsoftware.com/blog/?p=74
I have searched through the internet, and understand that the only way to change the body of a store procedure is by dropping and creating it again. There seems nothing wrong with the mechanism but if I have a client application (or thousands of distributed clients) that keeps invoking the store procedure to update some data on the server database, dropping the procedure would result in data lost and/or corruption.
I'm thinking if there is a syntax like "CREATE PROCEDURE IF EXIST..." or something functions similarly so the update operation would be carried out smoothly. Yet I didn't find such thing being available in MySQL.
So how do you guys think this issue can be addressed? Awesome thoughts?
You cannot modify a stored procedure (though you can change its characteristics) in MySQL. From the ALTER PROCEDURE page.
This statement can be used to change the characteristics of a stored
procedure. More than one change may be specified in an ALTER PROCEDURE
statement. However, you cannot change the parameters or body of a
stored procedure using this statement; to make such changes, you must
drop and re-create the procedure using DROP PROCEDURE and CREATE
PROCEDURE.
While it is possible to lose data while performing this update (though it should be a relatively small window), it's unlikely that your data will be corrupted. I'd take a look at message queuing technologies if your system needs to be guarded against data loss from database downtime.
I have a set of MYSQL tables on the development server that I need to place on the production server. How can I "recreate" all of them?
There are triggers present as well (I think). I need to recreate everything.
Use mysqldump to create a dump file that you can feed to mysql on the target server.
To make sure triggers get exported too, use the --triggers option. (Although I think those are included by default.)
To make sure stored procedures get exported too, use the --routines option. Note that (emphasis mine):
This option was added in MySQL 5.1.2. Before that, stored routines are not dumped. Routine DEFINER values are not dumped until MySQL 5.1.8. This means that before 5.1.8, when routines are reloaded, they will be created with the definer set to the reloading user. If you require routines to be re-created with their original definer, dump and load the contents of the mysql.proc table directly as described earlier.
Use mysqldump (documentation located here). If you do not specify tables it assumes all tables. You can also explicitly choose tables to copy or to ignore. You can tell it to create drop statements before your create statements. It takes cares of triggers but I forget if it takes care of routines, you'll have to take a look.