IF/THEN statement producing syntax error in MySQL - mysql

I have a very basic IF statement written that will be a part of a trigger, but when I try to run the query I receive a syntax error:
IF (STR_TO_DATE('09/29/2017','%m/%d/%Y') > CURDATE() - INTERVAL 1 DAY) THEN
SELECT * FROM apikeys;
END IF;
This is the error I'm getting:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'END IF' at line 1
I'm using MySQL 5.6
UPDATE: I now understand that IF/THEN statements can only be stored in procedures like triggers and are unable to be executed in this manner normally. Is there any way of knowing a trigger will be successful before implementing the new code into a live system? This trigger specifically controls a text messaging queue that fires SMS through Twilio, so I really cannot afford to guess and check.

Procedural logic in MySQL is only usable in stored procedures, triggers, events, etc... You cannot conditionally execute a query outside of those places (or client code obviously); the closest you can get is to make the IF's condition a part of the query's WHERE conditions. You still get a result set, but it will be empty.
SELECT *
FROM apikeys
WHERE STR_TO_DATE('09/29/2017','%m/%d/%Y') > CURDATE() - INTERVAL 1 DAY
;
Edit: In situations where you absolutely positively need procedure logic; you can create a stored procedure with it, execute that, and then drop the procedure.
Edit2:
Is there any way of knowing a trigger will be successful before
implementing the new code into a live system?
Seems, obvious but the best way to know is to run it on a test system. If that is not an option for some reason, as long as you are not using the NEW or OLD features of triggers you should be able to copy it into the body of a test procedure and run that instead...but you also won't get warned if you have queries that attempt to modify the table the trigger is on.

Related

When are MYSQL delimiters useful?

I am writing SQL to create a trigger for a table in my database. This code should be in a script we can run whenever we spawn a new database.
I have been reading the SQL doc to understand how to do this and eventually came up with a query of this type:
DELIMITER $$
CREATE TRIGGER calendar_event_after_insert AFTER INSERT
ON calendar_event
FOR EACH ROW
BEGIN
IF #log_calendar_event_id = 'YES'
THEN
...
END IF;
IF #log_calendar_event_name = 'YES'
THEN
...
END IF;
...
END
$$
DELIMITER ;
Now I am getting an error on my use of DELIMITER, and I admit I don't understand much of how that works. My basic understanding is that since there are multiple queries inside this big one that all end with a ; I need to tell sql when this query ends using another delimiter.
After reading a bit about delimiters this seems like the right syntax to me, and on top of that i have been running this query in sequel pro and it works at times and at times it does not (weird, I know).
So eventually I decided to remove the delimiters part and everything works smoothly. I am a bit worried this will have side effects tho.
So my question is: when are delimiters used? are they useful in my case? if so, what am I doing wrong here?
EDIT as requested in comments
This is the error I get when running the query:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'DELIMITER $$ CREATE TRIGGER calendar_event_after_insert AFTER
INSERT ON calenda' at line 1
FYI we have an old version of MYSQL installed on our dev machines -- MYSQL 5.1.73
DELIMITER is not part of the SQL language. It's a command of the official command-line tool:
If you use the mysql client program to define a stored program containing semicolon characters, a problem arises. By default, mysql itself recognizes the semicolon as a statement delimiter, so you must redefine the delimiter temporarily to cause mysql to pass the entire stored program definition to the server.
To redefine the mysql delimiter, use the delimiter command.
There're some third-party programs that also implement a delimiter command in order to be able to run complex MySQL scripts (e.g. HeidiSQL).
If you are running your script in a context that doesn't allow multiple statements (e.g. a typical PHP application) the command will neither exist nor be needed at all.

Call a Stored Procedure in SSIS Data Source

I am trying to call a stored procedure in SSIS OLE- DB DataSource (My Datasource would be SQL Server 2012).
I tried a procedure call SQL statement under SQL Command option but when I click the preview button I am getting an error.
Please guide me how to resolve this error. I goolged but nothing works for me.
I think the issue you are having is in SSIS often takes the first Select statement it finds and tries to validate it for column names, this happens especially with very big procedures. The trick I have found to get this to work is, right off the bat throw something like :
IF 1 = 0
Begin
Select all columns you want
END
This code will never get execute but it hints SSIS to make those columns the ones in the data flow. Just be sure to update this list as you update your last select.

Getting message Review the SQL script to be applied on the database

I am getting the following message while creating a stored procedure in MySQL Workbench:
"Review the SQL script to be applied on the database"
I have several tables inside the database but the stored procedure I am writing will be
used only for one table. Since, the SQL script of stored procedure is gonna apply on the whole database, I am wondering if it's gonna affect other tables as well? I don't want other tables to get disturbed because of this script.
Please provide your inputs as I am doing this for the first time.
Question #2:
Why do I see "DELIMITER $$" as the first statement while creating a routine before the following statement?
CREATE PROCEDURE `mydatabase`.`myfirstroutine` ()
BEGIN
Thanks
1) MySQL Workbench offers the option to review the generated SQL script before it is sent to the server. This way you can check it for possible problems.
2) The DELIMITER command is usually necessary to switch the current delimiter that ends a single statement (which is by default a semicolon) to something else because the stored procedure code itself needs the semicolon to separate individual commands. However the sp code must be sent as a whole to the server.
A few more details: the DELIMITER keywword is a client keyword only, that means the server doesn't know it and doesn't need it. It's an invention for clients to properly separate sql commands before sending them to the server (you cannot send a list of commands to a server, only individual statements).
In MySQL Workbench however, especially in the object editors where you edit e.g. the sp text, adding the DELIMITER command is essentially nonsense, because there's only this sp code, hence nothing to separate. This might disappear in future version but for now just ignore it.

Conditional/Executable Comments in MySQL/SQL Server

Before I begin, I realize that what I'm attempting is bizarre and hackish. It's just for an isolated pen test, specifically SQL Injection.
What I need to do is write a SQL statement that behaves differently when executing on a MySQL database than it does when executing on a SQL Server Database.
Edit
The limitation of the Query I can build is that I can only change what's after the "WHERE id =" clause. I can't affect any other part of the query. Specifically, I need to be able to attach a " UNION SELECT * FROM some_other_table" that only gets executed by the SQL server to the end of my input.
This obviously would blow up MySQL because it doesn't have the tables I'm unioning.
Specifically:
SELECT * FROM USERS
WHERE id = My input -> (MySQL code: 'x' or 1=1 )
(MSSQL code 'x' or 1=1 UNION SELECT * FROM table)
The problem is, if either statement gets executed by the database it wasn't meant for, it blows up (and not in the way I need it to).
This lead to my discovery of Conditional/Executable Comments in MySQL.
SELECT * FROM USERS
WHERE id = /*! This will be executed but only by mysql */
That's great but I still can't prevent MySQL from executing MSSQL! I can only stop MSSQL from executing MySQL code.
My initial idea was to have a comment inside the MySQL conditional like:
SELECT * FROM USERS
WHERE id = /*! 4 or 1=1 --*/ MSSQL code that is ignored by mysql
But this throws an error saying to check my syntax at a line with nothing on it near ''.
I don't fully understand why this doesn't work but I know doesn't work with any form of MySQL comment I know of (Tried #, /*).
Is there a way to get my strange SQL statement to work? Or is there a way to do a conditional comment in MSSQL? I really just need MySQL to ignore anything after it's conditional but I have no idea how to make that happen without comments.
I'm not sure if this is what you need, but if I understand correctly you want one SQL statement that returns different results on MySQL vs. SQL Server (if that's what "behaves differently" means?). If so, one place to start would be using a system function that has the same name and syntax but different behaviour, such as SUBSTRING():
select substring('test', -1, 1)
On SQL Server that returns an empty string, but on MySQL it returns t. I don't know if using SUBSTRING() is viable in your case, but if not you may be able to find another function that's easier to use in your query.
If this doesn't help at all then I suggest you provide some more details about what limitations you have in building your query.

Catch error in MYSQL

I want to implement a batch MySQL script to do something in a database. The thing is that, for each master id that I have I want to insert 4 tuples. But this tuples should be added in a transaction which means if one of these 4 tuples is failed the transaction should be rollback. Then I need to have some catching mechanism to capture that the query is failed. I CAN ONLY USE PURE MYSQL neither PHP, nor PERL etc. Even I cannot create any store procedure to do that. In Microsoft SQL Server there is ##error variable that solved my problem but in MYSQL we do not have any system variables showing the error code.
how can I do that?
Cheers,
This is an ugly workaround, but it worked for me when I was trying to import a batch of SQL queries and wrap the entire thing within a transaction, so that I could roll back if any of the SQL queries errored.
Since the size of the batch was massive, a SQL procedure with condition handler was not an option either.
You have to do this manually, so it really isn't a solution unless you are batching:
First, make sure your entire batch is stored in an SQL file. The SQL file should only contain the batch queries, and no transaction control queries.
Then start up a MySQL command line client and type in transaction commands manually:
mysql> SET AUTOCOMMIT = 0;
mysql> START TRANSACTION;
Then tell the command line client to run the batch file:
mysql> SOURCE path/to/file.sql
After that you can simply manually COMMIT; or ROLLBACK; depending on how happy you are with the result of your queries.
This is such a kludge, though. Anyone have a better approach?