In older versions of MySQL there was an option to analyze existing tables:
SELECT * FROM `table_name` PROCEDURE ANALYSE()
That seemed useful, a developer could analyze existing tables, see recommendations (for example use smallint instead of int) and consider some of them.
In MySQL 8.0 PROCEDURE ANALYSE() was removed. The reason I found:
"Reasoning: it was discussed many times that the PROCEDURE ANALYZE
syntax is an anachronism and almost unused non-standard syntax
extension".
Is this the only reason or analyzing tables automatically is a bad practice (even as just an additional instrument for analyze)?
Also I can't find any analogue of "Procedure Analyse" in Postgresql.
I know that I can analyze queries, but I suppose that it is useful to analyze table structure to consider it in architecture of new tables.
This feature is gone and no clear successor that I can find is provided or referenced in the documentation. I attempted to email the guy responsible for this, he no longer works at MySQL and his personal email is dead, so maybe his work was cut short. It's a shame they removed PROCEDURE ANALYSE that users relied on without providing a replacement stored procedure that they talked about.
One can analyse tables manually with statements such as:
select MAX(LENGTH(address1)) from places;
select address1 from places where length(address1) > 99;
Related
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.
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.
Red Gate has some pretty good tools, but I don't think that their Dependency Tracker shows how Tables are effected by the stored procedures that touch them.
Is there any tool that can scan a database and determine what processes INSERT, UPDATE or DELETE records from the table as opposed to just touching\being dependent on them? Seems like this shuld exist by now...
No, dependency tracking still isn't perfect. The reason is that procedures can reference tables by dynamic SQL, dependencies can be broken if objects are dropped and re-created (I've written about how dependencies can break here). The best "first sweep" I have come to rely on is:
SELECT OBJECT_NAME([object_id])
FROM sys.sql_modules
WHERE LOWER(definition) LIKE '%table_name%';
Again, this won't find objects that build statements using dynamic SQL, and it can produce false positives because table_name could be simplistic and part of other object or parameter names, or included only in comments or commented-out code.
You can also check for plans that reference a table using sys.dm_exec_cached_plans and related DMFs/DMVs but note that this won't find any plans that have rolled out of the cache.
Using SQL Search, you can search for the column name and find all the stored procedures where it is used.
It's a Third Party tool and that is Red Gate SQL Search
Features
Find fragments of SQL text within stored procedures, functions, views
and more
Quickly navigate to objects wherever they happen to be on a server
Find all references to an object
Hope this will help you.
Does anyone know of a way to embed comments in MySQL statements? When I search for mysql and comments I get only ways to put comments in tables, etc
The idea, if I implement this the way my boss wants it, is to prepend the user id to the statement apparently so that when MySQL is analyzed later (via the binary log) we know who did what.
Example:
SELECT id
FROM customer
WHERE handle='JBH'
Would now show up as:
-- user:jwilkie
SELECT id
FROM customer
WHERE handle='JBH'
(or similar)
EDIT FOR CLARITY: The reason for this is that we have perl modules that are interfacing with MySQL and we are retrieving the user id by reading $ENV{USER} (which in this case is "jwilkie"). It is a situation where we have one MySQL user defined but multiple people running the perl mod.
Does anyone have experience with this? Many many thanks! Jane
Normally, comments are stripped before the SQL statement is recorded in the binary log. However, a nasty workaround is to pretend that ypur comment contains syntax for some future version of MySQL - eg. 9.99.99:
/*!99999 user:jwilkie */ insert into tbl values (yyy);
These comments will then be passed through into the binary log.
If you have control over the SQL queries being generated, then you should be able to embed comments in them programatically in your query builder.
Select queries don't go in the binary log, but the comments may make it into the slow query log, general query log, etc.
Here's a blog post from Percona that touches on the subject a bit, specifically in the context of mk-query-digest. It might help:
http://www.mysqlperformanceblog.com/2010/07/05/mk-query-digest-query-comments-and-the-query-cache/
In Microsoft Sql it is possible to encrypted stored procedures with
CREATE PROCEDURE dbo.foo
WITH ENCRYPTION
AS
BEGIN
SELECT 'foo'
END
This stops people looking at stored procedures code.
How can I do this in MySql 5.0.x ?
You can not do this in MySQL. See bug #4210.
[Edit]: The comment from Leonidas on another answer to this question needs to be out there for anyone to read, so I'm quoting it here:
Obfuscation can be reversed. I found
at least one product via Google, that
promises to reveal the SP-code. So I
think/hope that the MySQL-team won't
bother with "security by obscurity" or
even worse "intellectual asset
protection" (as described in the bug
4210).
It looks like its been requested before but I don't know if they're considering it.