Performing Interactive queries in MySQL (mainly from the GUI) - mysql

I mainly use the MySQL GUI tools. This allows me to easily see the results in a table as well as to quick edits and bookmark frequently run queries. This suits my needs far better than the command line.
I remember when I used to do this on Oracle DBs years ago I could put variables in the query itself, so that when running the query I got prompted for the variable.
e.g.
select email from users where login = [VAR]
And when you run the query the system prompts you for VAR and you can type in john_smith14 and it executes the query. This is really useful for adhoc queries which you run a lot.
Yes I know using shell scripts and the command line this could be done more easily, but for several reasons aside from this, shell scripts are not a good solution for me.

Ok, a different solution, since it appears Bill is right (read the comments on my other answer).
In the Params tab in the bottom right, you can right click the "Local Params" folder and add a new parameter. Give it a name, eg: "myTest". Initially it is given a value of NULL. Double click on NULL and type in a new value.
Now you can access it in your query like this:
SELECT email FROM users WHERE login = :myTest;
To make this persist between sessions (opening and closing the query browser), just make it a global parameter instead of a local parameter. This works even if you restart the MySQL server.

I'm not sure if there's a way to get the GUI tools to prompt you for a value, but you can certainly use variables in MySQL.
SET #myVar='john_smith14';
SELECT email FROM users WHERE login = #myVar;
That might even suit you better, since you don't have to keep typing in the variable value each time..?

Using prepared statements might be useful for you in this case.
PREPARE query1 FROM select email from users where login = ?
then execute it with your variable:
SET #a = 'john';
EXECUTE query1 USING #a;
This statement will be there during your whole session, and dropped when you disconnect.
This might seem like much overhead, but is useful when using the same query over and over again, with slightly different values.
http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html

Related

Microsoft Access: Set a global variable on table open, use it as criteria for queries, and clear it on table close

I want to be able to ask the user for a global variable on tableopen on specific tables, use it as a criteria for sub-queries, and clear it on tableclose.
To use it in queries, I've found the getglobal SQL function which should do it fine, however I couldn't find a way to query the variable to the user on table open and clear it on table close.
Any help welcome.
There's no way to do this, as there's no way to call a function on table open. Typically, you would either put a prompt in a query to ask the user for a value when running the query, or have a form set up where the user is prompted for a value, and then open the query/report while referencing the control with the value in it.
Why would you ever let a user open a table?? This is asking for trouble. Give them a GUI, take their input and run whatever you need to run on the back end.

Mysql Workbench - The best way to organize running frequently used SQL queries while development

I'm a java dev who uses Mysql Workbench as a database client and IntelliJ IDEA as an IDE. Every day I do SQL queries to the database from 5 up to 50 times a day.
Is there a convenient way to save and re-run frequently used queries in Mysql Workbench/IntelliJ IDEA so that I can:
avoid typing a full query which has already been used again
smoothly access a list of queries I've already used (e.g by auto-completion)
If there is no way to do it using Mysql Workbench / IDEA, could you please advise any good tools providing this functionality?
Thanks!
Create Stored Procedures, one per query (or sequence of queries). Give them short names (to avoid needing auto-completion).
For example, to find out how many rows in table foo (SELECT COUNT(*) FROM foo;).
One-time setup:
DELIMITER //
CREATE PROCEDURE foo_ct
BEGIN;
SELECT COUNT(*) FROM foo;
END //
DELIMITER ;
Usage:
CALL foo_ct();
You can pass arguments in in order to make minor variations. Passing in a table name is somewhat complex, but numbers of dates, etc, are practical and probably easy.
If you have installed SQLyog for your mysql then you can use Favorites menu option in which you can save your query and in one click it will automatically writes the saved query on Query Editor.
The previous answers are correct - depending on the version of the Query Browser they are either called Favorites or Snippets - the problem being you can't create sub-folders to group them. And keeping tabs open is an option - but sometimes the browser 'dies' - and you're back to ground 0. So the obvious solution I came up with - create a database table! I have a few 'metadata' fields for descriptions - the project a query is associated to; problem the query solves; and the actual query.
You could keep your query library in an SQL file and load that when WB opens (it's automatically opened when you restart WB and that file was open on last close). When you want to run a specific query place the caret in it's text and press Ctrl+Enter (Cmd+Enter on Mac) to run only this query. The organization of that SQL file is totally up to you. You have more freedom than any "favorites" solution can give you. You can even have more than one file with grouped statements.
Additionally, MySQL Workbench has a query history (see the Output Tab), which is saved to disk, so you can return to a query even month's after you wrote it.

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.)

sending terminal/shell command from mysql to terminal and retrieve answer while looping cursor

I'm using php with MySQL on macOS.
I would like to select a large amount of emails from a database and perform a dns lookup for each email in my selection using a dig command from the terminal/shell, something like: "dig gmail.com" .
Of course, I can loop this select through php but it will be very slow compared to looping cursor on MySQL.
How to send terminal commands from mysql to the terminal and retrieve answer on macOS?
You can't execute shell commands from within an SQL query (thank god), or else it would be a horrible security vulnerability... You would have to do it from php.
P.S. It is however possible to execute shell commands from the MySQL command line utility
\! ls
...but if I understand your question, it won't help solve your current problem.
(I'm assuming that you really mean ADDR_SPEC when you're talking about email addresses)
but it will be very slow in compare with looping cursor on mysql
No not really. The only difference is that depending on how you implement this the PHP approach requires that you retrieve the entire result set before you start iterating through it. However breaking this up into smaller result sets is trivial.
Also, the limitation on the performance of your algorithm is the speed of DNS lookups - and that's all about latency - if your objective is to make this go faster then you should be running multple requests in parallel.
The next thing you should consider is that you've probably got multiple mailboxes for each MX, e.g. user1#gmail.com, user2#gmail.com.... While if you've got DNS caching setup properly there will be less overhead than going to the source each time, if you're working with a very large data set or will be doing this more than once, it makes a lot more sense to just work with unique MX host values, e.g.
SELECT DISTINCT SUBSTR(addr_spec FROM LOCATE('#', addr_spec)) AS mx2chk
FROM yourtable
WHERE addr_spec LIKE '%#%'
AND (email_checked IS NULL
OR email_checked<NOW() - INTERVAL 300 DAY )
;
Indeed, if your flagging the data then you can use your own database to verify the MX.
using a dig command from terminal/shell
Please don't tell me that you're running a shell from a PHP controlling process to do a DNS lookup?

MySQL Injection - Use SELECT query to UPDATE/DELETE

I've got one easy question: say there is a site with a query like:
SELECT id, name, message FROM messages WHERE id = $_GET['q'].
Is there any way to get something updated/deleted in the database (MySQL)? Until now I've never seen an injection that was able to delete/update using a SELECT query, so, is it even possible?
Before directly answering the question, it's worth noting that even if all an attacker can do is read data that he shouldn't be able to, that's usually still really bad. Consider that by using JOINs and SELECTing from system tables (like mysql.innodb_table_stats), an attacker who starts with a SELECT injection and no other knowledge of your database can map your schema and then exfiltrate the entirety of the data that you have in MySQL. For the vast majority of databases and applications, that already represents a catastrophic security hole.
But to answer the question directly: there are a few ways that I know of by which injection into a MySQL SELECT can be used to modify data. Fortunately, they all require reasonably unusual circumstances to be possible. All example injections below are given relative to the example injectable query from the question:
SELECT id, name, message FROM messages WHERE id = $_GET['q']
1. "Stacked" or "batched" queries.
The classic injection technique of just putting an entire other statement after the one being injected into. As suggested in another answer here, you could set $_GET['q'] to 1; DELETE FROM users; -- so that the query forms two statements which get executed consecutively, the second of which deletes everything in the users table.
In mitigation
Most MySQL connectors - notably including PHP's (deprecated) mysql_* and (non-deprecated) mysqli_* functions - don't support stacked or batched queries at all, so this kind of attack just plain doesn't work. However, some do - notably including PHP's PDO connector (although the support can be disabled to increase security).
2. Exploiting user-defined functions
Functions can be called from a SELECT, and can alter data. If a data-altering function has been created in the database, you could make the SELECT call it, for instance by passing 0 OR SOME_FUNCTION_NAME() as the value of $_GET['q'].
In mitigation
Most databases don't contain any user-defined functions - let alone data-altering ones - and so offer no opportunity at all to perform this sort of exploit.
3. Writing to files
As described in Muhaimin Dzulfakar's (somewhat presumptuously named) paper Advanced MySQL Exploitation, you can use INTO OUTFILE or INTO DUMPFILE clauses on a MySQL select to dump the result into a file. Since, by using a UNION, any arbitrary result can be SELECTed, this allows writing new files with arbitrary content at any location that the user running mysqld can access. Conceivably this can be exploited not merely to modify data in the MySQL database, but to get shell access to the server on which it is running - for instance, by writing a PHP script to the webroot and then making a request to it, if the MySQL server is co-hosted with a PHP server.
In mitigation
Lots of factors reduce the practical exploitability of this otherwise impressive-sounding attack:
MySQL will never let you use INTO OUTFILE or INTO DUMPFILE to overwrite an existing file, nor write to a folder that doesn't exist. This prevents attacks like creating a .ssh folder with a private key in the mysql user's home directory and then SSHing in, or overwriting the mysqld binary itself with a malicious version and waiting for a server restart.
Any halfway decent installation package will set up a special user (typically named mysql) to run mysqld, and give that user only very limited permissions. As such, it shouldn't be able to write to most locations on the file system - and certainly shouldn't ordinarily be able to do things like write to a web application's webroot.
Modern installations of MySQL come with --secure-file-priv set by default, preventing MySQL from writing to anywhere other than a designated data import/export directory and thereby rendering this attack almost completely impotent... unless the owner of the server has deliberately disabled it. Fortunately, nobody would ever just completely disable a security feature like that since that would obviously be - oh wait never mind.
4. Calling the sys_exec() function from lib_mysqludf_sys to run arbitrary shell commands
There's a MySQL extension called lib_mysqludf_sys that - judging from its stars on GitHub and a quick Stack Overflow search - has at least a few hundred users. It adds a function called sys_exec that runs shell commands. As noted in #2, functions can be called from within a SELECT; the implications are hopefully obvious. To quote from the source, this function "can be a security hazard".
In mitigation
Most systems don't have this extension installed.
If you say you use mysql_query that doesn't support multiple queries, you cannot directly add DELETE/UPDATE/INSERT, but it's possible to modify data under some circumstances. For example, let's say you have the following function
DELIMITER //
CREATE DEFINER=`root`#`localhost` FUNCTION `testP`()
RETURNS int(11)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DELETE FROM test2;
return 1;
END //
Now you can call this function in SELECT :
SELECT id, name, message FROM messages WHERE id = NULL OR testP()
(id = NULL - always NULL(FALSE), so testP() always gets executed.
It depends on the DBMS connector you are using. Most of the time your scenario should not be possible, but under certain circumstances it could work. For further details you should take a look at chapter 4 and 5 from the Blackhat-Paper Advanced MySQL Exploitation.
Yes it's possible.
$_GET['q'] would hold 1; DELETE FROM users; --
SELECT id, name, message FROM messages WHERE id = 1; DELETE FROM users; -- whatever here');