Saving commands for later re-use in MySQL? - mysql

What would be the equivalant in MySQL for:
Saving a command for later reuse.
eg: alias command1='select count(*) from sometable;'
Where then I simply type command 1 to get the count for SomeTable.
Saving just a string, or rather part of a command.
eg: select * from sometable where $complex_where_logic$ order by attr1 desc;
WHere $complex_where_logic$ is something I wish to save and not have to keep writing out

Another approach is to create a view with your $complex_where_logic$ and query the view instead of the tables:
CREATE VIEW my_view AS SELECT * FROM sometable WHERE $complex_where_logic$
SELECT my_column FROM my_view ORDER BY some_column
Whenever you query a view, you always get the up-to-date data. Internally, MySQL runs the SELECT given in the CREATE VIEW statement and queries the results in order to obtain the results of your current SELECT. Therefore, a view does not improve performance compared to a single query. There a two main advantages in using views:
you have simpler SELECT statements since you do not have to type complex WHERE or JOIN Syntax again and again
you can use it to control user privileges, e.g. give a user access to a view but not to the original tables; this is not useful in your example, but - for example - you can think of views containing aggregate data only

This "template" feature could be part of client tools. Basically I use Toad. It has record macros feature. I think it is possible to do.

I take it the answer you are looking for isn't 'stored procedures'...?

I found that the best solution for this is just any rich GUI for SQL queries (TOAD, mysql query browser, etc). They offer the ability to save commands and browse them and well, of course, much more.

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.

Problem with union the table which not exists

I want to get data from several tables which has the same column name in one SQL statement, for example:
SELECT name, age FROM table_a UNION SELECT name, age FROM table_b UNION...
But the table_x may not exists that I can't avoid from people who send the request to me, if one of the tables is not exits in a query it will be failed, is there any syntax to avoid that?
I know a way that I can use show tables to get all tables in the database and compare them to the request parameters first, but I hope I can do it from MySQL syntax.
The short answer is no. If you are using another language in front of it, such PHP or any other language really, you can query the tables as you suggest, but SQL expects the query to be accurate syntactically and if it's not it will error. There is one (IMO bad) way to do this, if you must. You could use a stored procedure, which would allow you to dynamically build the query as you would in PHP or another language, but that's about all you have with MySQL (or any database that I know).

Reverse string with leading wildcard scan in Postgres

SQL Server: Index columns used in like?
I've tried using the query method in the link above with Postgres (0.3ms improvement), it seems to only work with MySQL (10x faster).
MYSQL
User Load (0.4ms) SELECT * FROM users WHERE reverse_name LIKE REVERSE('%Anderson PhD')
User Load (5.8ms) SELECT * FROM users WHERE name LIKE ('%Anderson Phd')
POSTGRES
User Load (2.1ms) SELECT * FROM users WHERE reverse_name LIKE REVERSE('%Scot Monahan')
User Load (2.5ms) SELECT * FROM users WHERE name LIKE '%Scot Monahan'
Did some googling but couldn't quite understand as I'm quite new to DBs. Could anyone explain why this is happening?
To support a prefix match in Postgres for character type columns you either need an index with a suitable operator class: text_pattern_ops for text etc. (Unless you work with the "C" locale ...)
Or you use a trigram index to support any pattern - then you don't need the "reverse" trick any more.
See:
PostgreSQL LIKE query performance variations
You'll see massive performance improvement for tables of none-trivial size, as soon as an index can be used for the query. Have a look at the query plan with EXPLAIN.

MySQL views performance with select * from tablename definition

I have created views with following generic definition on all of my tables required for reporting
select * from tablename
Ideally views with this definition should use merge algorithm.
Can someone please tell me if the performance of these views with the above definition will be comparable to the physical tables?
Check out this link.
By above report, derived table shows poor performance than table, while simple view works good. But if you run a query with ORDER or WHERE on view, it will be slower than naive table. (see comments on the link )
And use EXPLAIN to checkout your queries between view and table.

Allow only Selects for a MySQL user with many privileges

I am creating a database application that provides dynamic views of any database. For security features, I want to only allow selects. Can this simply be done by checking if the first word is select? I know that I should have another created user with limited permissions but I am trying to avoid that so that my app is easy to use.
Basically, can someone give me an example query of where SELECT is the first word but the data can actually be altered?
can someone give me an example query of where SELECT is the first word
but the data can actually be altered?
No such thing. SELECT is for data reading only. Unless, of course, your are selecting a function that alters data. See #spencer7593 answer.
However, you might want to check for row blocking SELECT commands and also avoid them, since it appears that you will open your DB to 3rd parties.
Further reading: http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html
Here's an example of a SELECT statement that can modify data (it's an obscure corner case, but it demonstrates that it IS possible to cause data to be modified with a SELECT)
SELECT udf_myfunction()
Given, e.g.:
CREATE FUNCTION udf_myfunction() RETURNS INT
READS SQL DATA
BEGIN
DELETE FROM dummy_table1;
UPDATE dummy_table2 SET mycol = CONCAT(mycol,SUBSTR(mycol,1,1));
RETURN 0;
END
(Of course, the user would need to be granted EXECUTE privilege on the function, in order for the function to be executed.)