Why is SELECT..PROCEDURE a MySQL syntax error? [closed] - mysql

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I want to run a MySQL query and then process all the result sets. The MySQL
5.7 documentation says that the way to do is to use SELECT ... PROCEDURE
stored_procedure_name(parameters). I created a stored procedure that does what I want without any problems. I used it in a SELECT ... PROCEDURE query and got this syntax error:
ComposeStatement (identifier) is not valid at this position
(where ComposeStatement is the name of my stored procedure). I checked I have the proper number of parameters and they are of the proper type. Using a
different procedure gives the same error (with the obvious change in name).
The documentation shows an example of this syntax using a procedure called
ANALYSE (which I understand from another post is now deprecated, but I really don't care about using ANALYSE specifically). When I tried the example I get the same error, with ANALYSE as the identifier. The errors I'm getting are
not in the procedures themselves, which is why many earlier posts don't apply.
Any suggestions? The SELECT..PROCEDURE construct sounds like it's exactly
what I need.

The MySQL feature #LarryGriffith references has nothing to do with stored procedures.
It's related to this deprecated feature: https://dev.mysql.com/doc/refman/5.7/en/procedure-analyse.html
SELECT col1, col2 FROM table1 PROCEDURE ANALYSE(10, 2000);
This use of the PROCEDURE query modifier is like putting a filter function on the result set from a query. It's analogous to a pipeline in the shell:
ls | grep myfile
The thing is, the "procedure" you use (ANALYSE() in the example) is not a stored procedure of the type you can write with CREATE PROCEDURE.
You would have to code the filtering function in C++ and compile it with the MySQL source.
The ANALYZE() example was originally meant as a proof of concept or example that developers could follow if they wanted to develop their own query filters. But I've never heard of anyone who actually did create a query filter of their own.
Last year it was announced that the SELECT ... PROCEDURE ANALYZE() feature was intended to be deprecated in MySQL 8. http://www.tocker.ca/2015/06/29/plan-to-deprecate-procedure-analyse.html
If you need to post-filter a query result, it's far easier to write a script (in Python or whatever your favorite language is), which fetches the raw data from the query result, and then does whatever you need to do with it.

Related

Save MySql 'Show' result in db

So I'm kind of stumped.
I have a MySql project that involves a database table that is being manipulated and altered by scripts on a regular basis. This isn't so unusual, but I need to automate a script to run (after hours, when changes aren't happening) that would save the result of the following:
SHOW CREATE TABLE [table-name];
This command generates the ready-to-run script that would create the (empty) table in it's current state.
In SqlWorkbench and Navicat it displays the result of this SHOW command in a field in a result set, as if it was the result of a SELECT statement.
Ideally, I want to take into a variable in a procedure, and change the table name; adding a '-mm-dd-yyyy' to end of it, so I could show the day-to-day changes in the table schema on an active server.
However, I can't seem to be able to do that. Unlike a Select result set, I can't use it like that. I can't get it in a variable, or save it to a temporary, or physical table or anything. I even tried to return this as a value in a function, from which I got the error that a function cannot return a result set - which explains why it's displayed like one in the db clients.
I suspect that this is a security thing in MySql? If so, I can totally understand why and see the dangers exposed to a hacker, but this isn't a public-facing box at all, and I have full root/admin access to it. Hopefully somebody has already tackled this problem before.
This is on MySql 8, btw.
[Edit] After my first initial comments, I need to add; I'm not concerned about the data with this question whatsoever, but rather just these schema changes.
What I'd really -like- to do is this:
SELECT `Create Table` FROM ( SHOW CREATE TABLE carts )
But this seems to be mixing apples and oranges, as SHOW and SELECT aren't created equal, although they both seem to return the same sort of object
You cannot do it in the MySQL stored procedure language.
https://dev.mysql.com/doc/refman/8.0/en/show.html says:
Many MySQL APIs (such as PHP) enable you to treat the result returned from a SHOW statement as you would a result set from a SELECT; see Chapter 29, Connectors and APIs, or your API documentation for more information. In addition, you can work in SQL with results from queries on tables in the INFORMATION_SCHEMA database, which you cannot easily do with results from SHOW statements. See Chapter 26, INFORMATION_SCHEMA Tables.
What is absent from this paragraph is any mention of treating the results of SHOW commands like the results of SELECT queries in other contexts. There is no support for setting a variable to the result of a SHOW command, or using INTO, or running SHOW in a subquery.
So you can capture the result returned by a SHOW command in a client programming language (Java, Python, PHP, etc.), and I suggest you do this.
In theory, all the information used by SHOW CREATE TABLE is accessible in the INFORMATION_SCHEMA tables (mostly TABLES and COLUMNS), but formatting a complete CREATE TABLE statement is a non-trivial exercise, and I wouldn't attempt it. For one thing, there are new features in every release of MySQL, e.g. new data types and table options, etc. So even if you could come up with the right query to produce this output, in a couple of years it would be out of date and it would be a thankless code maintenance chore to update it.
The closest solution I can think of, in pure MySQL, is to regularly clone the table structure (no data), like so:
CREATE TABLE backup_20220618 LIKE my_table;
As far as I know, to get your hands on the full explicit CREATE TABLE statement, as a string, would require the use of an external tool like mysqldump which was designed specifically for that purpose.

Having a hard time creating a procedure in SQL

I need to create a procedure for class, but I think the sql version in the book is VERY old. For example, I don't think I can't use "Create or replace" like the book says, but "create", "drop", "create", but that is beyond the scope.
My issue is that I am having trouble setting the %TYPE. I use WAMP, I created the procedure in Notepad++, and pasted it to the console. I then opened up phpmyadmin, pasted it into the query window, and was rewarded with more verbose error message. Book: "A guide to SQL" by Phil Pratt and Mary Last, Ninth Edition https://www.amazon.com/Guide-SQL-Philip-J-Pratt/dp/111152727X . Book has TAL Distributers, SOLARIS comdominium group, and COLONIAL adventure tours databases it that helps anyone. The instructor provided the sql file to create the databases as a time saver. This is for the last chapter, ch.8 Creation code:
delimiter ;;
use tal;;
CREATE PROCEDURE CHANGE_ITEM_PRICE(I_ITEM_NUM IN item.item_num%TYPE, I_NEW_PRICE IN item.price%TYPE) AS
BEGIN
UPDATE item SET price = I_NEW_PRICE
WHERE item_num = I_ITEM_NUM;
END;;
delimiter ;
2 Errors:
Unrecognized data type. (near "IN" at position 56)
and another for position 91.
Any thoughts? I'm not looking to be spoon fed here, I just need a little guidance please.
Edit: Thank you #Bill Karwin. The corrected working syntax follows:
delimiter ;;
use tal;;
CREATE PROCEDURE CHANGE_ITEM_PRICE(IN I_ITEM_NUM char(4), IN I_NEW_PRICE decimal(6,2))
BEGIN
UPDATE item SET price = I_NEW_PRICE
WHERE item_num = I_ITEM_NUM;
END;;
delimiter ;
I_ITEM_NUM IN item.item_num%TYPE
This is not a valid procedure argument declaration for MySQL. You have to name the type with something like INT or DATE or VARCHAR(length) or another known type. MySQL has no syntax like you show to dynamically query the type of a named column.
Out of curiosity, where did you get that syntax? Is it part of some other brand of SQL database? I've never seen it before.
Aha, I found it:
https://www.postgresql.org/docs/current/static/sql-createfunction.html says:
The type of a column is referenced by writing table_name.column_name%TYPE. Using this feature can sometimes help make a function independent of changes to the definition of a table.
That's in the PostgreSQL documentation. PostgreSQL and MySQL are not the same software, and there are many examples of syntax and features that each has that the other does not.
This syntax is also supported by Oracle: %TYPE attribute. Actually, I assume Oracle did it before PostgreSQL.
Re your comment:
var IN char(4)" does not work either
You said you were interested in a little guidance. The simplest guidance is that when you're learning a new syntax, it helps to read the reference documentation. :-)
I've used MySQL a lot over the past 16 years. I am a regular speaker at MySQL Conferences and users' groups. I'm a published author. And even I open the documentation pages as a first step when I'm doing something that isn't immediately familiar to me.
Here: http://dev.mysql.com/doc/refman/5.7/en/create-procedure.html
Notice when declaring procedure parameters, it's IN param_name type, not param_name IN type.
now the error is "syntax near ' AS....'
Again, refer to the documentation. There's no AS in the stored procedure syntax for MySQL. That's also Oracle syntax.
You may need to get a different book if you're going to use MySQL instead of Oracle. For example, I suggest MySQL Stored Procedure Programming: Building High-Performance Web Applications in MySQL.
But honestly, I am not a fan of using stored procedures in MySQL at all. MySQL's implementation of stored procedures is far inferior to that of Oracle. MySQL procedures have no packages or libraries, there's no procedure debugger, they're not compiled, and they don't scale well.
Most developers who use MySQL put more logic in their application code instead of stored procedures. This allows them to scale out their performance to numerous application servers, instead of piling up the load on the database server.
I don't believe MySQL has an equivalent for Oracle's %TYPE operator. You will need to specify the data types directly, for example:
CREATE PROCEDURE CHANGE_ITEM_PRICE(I_ITEM_NUM INT, I_NEW_PRICE DECIMAL) ...
I checked through the function and operator list in the most recent MySQL manual to see if they have recently added this function, but did not find it there.

What does SELECT ... PROCEDURE procedure_name do?

In reading through the documentation, I noticed that MySQL's SELECT syntax has a clause that I had never really caught before:
SELECT
...
[PROCEDURE procedure_name(argument_list)]
...
I am intrigued, since from what little I could understand from their terse explanation and their example with PROCEDURE ANALYSE, one can pass data (and possibly metadata as well?) from a SELECT statement into a stored procedure. However, searching elsewhere for more details didn't yield any results, and the source for the ANALYSE procedure proved elusive to SHOW PROCEDURE calls in every database.
I ask more out of curiosity, since I know nothing about it, but what is this clause for, and what can I do with it?
Here is an explanation by
Morgan Tocker (MySQL Community Manager)
http://www.tocker.ca/2015/06/29/plan-to-deprecate-procedure-analyse.html

SQL Server sp_help : how to limit the number of output windows

Normally successful execution of
sp_help [object_name]
in SQL Server returns a total of 7 output windows with various results out of which normally I am interested in only 2 windows namely the one with all the column information and the one with the constraints.
Is there a way I can tell SQLserver to only display these while formulating the command?
Short answer: no, you can't do this directly because the procedure is written to return that data, and TSQL has no mechanism for accessing specific result sets.
Long answer: but you can easily get the same information from other procedures or directly from the system catalog:
sp_columns, sp_helpconstraint (this is actually called by sp_help) etc.
sys.columns, sys.objects etc.
There's also the option of copying the source code from sp_help and using it as the basis of a new procedure that you create yourself, although personally I would just write it myself from scratch. If you do decide to write your own stored proc, you might find this question relevant too.

How can I view the error preventing me from creating a stored procedure?

I'm trying to implement a Haversine distance function as desribed in this question.
Whenever I run it though, either on the command line or through PhpMyAdmin, I get the following error:
#1607 - Cannot create stored routine `haversine`. Check warnings
The problem is that when I run SHOW WARNINGS; I get a 0 row result set.
Is this a common problem? How do I view the warnings? (If it's relevant, I'm running MySQL 5.1.37-1ubuntu5.)
Don't know if there is any better way. What I have been doing is to create it very simple and incomplete and test at each added bit of functionality. Why don't you post yours?
Look at this question:
How do you debug MySQL stored procedures?