MySQL schedule event : database backup including date in the outfile - mysql

I am struggling now in order to automatize my tiny backup system. I managed to gather some piece of code but I cannot make it.
SET #sql_text =
CONCAT (
"SELECT * FROM commandes INTO OUTFILE 'Y:/folder/Archives/BDD-commandes-CSV"
, DATE_FORMAT( NOW(), '%Y%m%d')
, "commandes.csv'"
);
PREPARE s1 FROM #sql_text;
CREATE EVENT BackUpCSV
ON SCHEDULE EVERY 1 HOUR
STARTS CURRENT_TIMESTAMP + INTERVAL 1 DAY
ENDS CURRENT_TIMESTAMP + INTERVAL 1 YEAR
DO
BEGIN
EXECUTE s1;
END |
DROP PREPARE s1;
Here is what i tried to do. An error is spotted at line 7 where it is actually a blank line ('#1064 - 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 '' at line 7')
I would be grateful to get this help. thx

There is all about delimiter. Here is the version which is fine to compile:
SET #sql_text =
CONCAT (
"SELECT * FROM commandes INTO OUTFILE 'Y:/folder/Archives/BDD-commandes-CSV"
, DATE_FORMAT( NOW(), '%Y%m%d')
, "commandes.csv'"
);
PREPARE s1 FROM #sql_text;
delimiter |
CREATE EVENT BackUpCSV
ON SCHEDULE EVERY 1 HOUR
STARTS CURRENT_TIMESTAMP + INTERVAL 1 DAY
ENDS CURRENT_TIMESTAMP + INTERVAL 1 YEAR
DO
BEGIN
EXECUTE s1;
END |
delimiter ;
DROP PREPARE s1;
Also, I recommend to add drop event if exists BackUpCSV |
ps. I'm not sure this script will work

For that purposes better use shell script, or command line. Something like this:
#!/bin/bash
mysqldump --add-drop-table -h <hostname> -u <username> --password=<password> --all-databases > filename.sql
filename="filename.sql."`eval date +%Y%m%d`".tgz"
tar -czf $filename filename.sql
rm filename.sql
You can save this to a file, and run that file as a cron job.
If you want you can even push that archive file to another system with same script.
Of course you should understand that in this case you're storing your database credentials in a plain file. But if someone has access to the filesystem I'm sure s/he will find your application config files where you do exactly the same.

Related

Setting Date Parameters in MYSQL

I am a beginner to MySQL and have written some basic MySQL stored procedures but cannot see what is wrong with the code below, I am getting the error
"Error Code: 1064. 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 '' at line 9"
CREATE PROCEDURE CA_Daily
(
DateTime_Start datetime
)
BEGIN
SET DateTime_Start = DATE_FORMAT((CURDATE() - INTERVAL 1 DAY ) ,'%Y%-%m-%d %T');
END;
There is a lot more to the original code which when I run it just as a piece of script works fine its just when I try to create it as a stored procedure it fails, I have it down to how I am dealing with the parameters but not sure what I am doing wrong....if not everything.
Any help would be great.
Please try this:
DELIMITER $$
CREATE PROCEDURE CA_Daily1
(
DateTime_Start datetime
)
BEGIN
SET DateTime_Start = DATE_FORMAT((CURDATE() - INTERVAL 1 DAY ) ,'%Y%-%m-%d %T');
END$$
You should use the STR_TO_DATE conversion in your SET statement:
Example:
STR_TO_DATE('8/21/2017 12:58 PM', '%c/%e/%Y %H:%i')

phpMyAdmin can't find syntax for Create EVENT

-mysql 5.6.2
-GLOBAL event_scheduler = ON
Using phpMyAdmin client on MYSQL database. I'm not setting a Delimiter, as I know you can't in this statement. If I remove the last ';', it fails with 'error near END.' In below format, fails with:
1064 - 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 '' at line 64
#Begin statement
CREATE EVENT airshipmentsnotinlong
ON SCHEDULE every 1 HOUR
ON COMPLETION PRESERVE
DO
BEGIN
INSERT into WORKORDERS
(
id
,client_id
,method
,carrier_id
,carrier
,username
,password
,blnumber
,containernumber
,bookingnum
,adddate
,moddate
,isdone
)
SELECT
DISTINCT 'null' as ID
,cs.customer_id as client_id
,'justin' as method
,cs.carrier_id
,c.scac
,'' as user
,'' as pass
,cs.blnumber
,cs.container
,'' as book
,now() as adate
,now() as modate
,'0' as done
FROM CUSTOMERSHIPMENTS CS
LEFT JOIN
SHIPMENTS S
ON
cs.container = s.containernumber
and cs.blnumber = s.blnumber
LEFT JOIN
CARRIERS C
ON
cs.carrier_id = c.id
WHERE
cs.hostcompany_id = cs.company_id
and cs.container like '.air%'
and cs.isactive = 1
and cs.hostcompany_id = company_id
and cs.carrier_id in (176,180,222,224,226,227,228,261,271,292,297)
and cs.date > NOW() - INTERVAL 3 MONTH
and cs.blnumber <> ''
#and s.status = ''
and cs.blnumber not in
(
SELECT
blnumber
FROM
workorder_log
WHERE
cdate > now()-interval 75 minute
)
;
END
Your understanding to the contrary notwithstanding, you need to set the delimiter. Do this.
DELIMITER $$
CREATE EVENT airshipmentsnotinlong
ON SCHEDULE every 1 HOUR
ON COMPLETION PRESERVE
DO
BEGIN
...your event's INSERT statement here including the closing semicolon ...
END $$
DELIMITER ;
In PHPMyAdmin, instead of wrapping your definition in DELIMITER $$ / DELIMITER ; you set the delimiter to something besides ; in the box right below the query. You then terminate your definition with that same delimiter, as I have shown in END$$.
The error message you're getting is protesting the missing END, which MySQL doesn't see because it comes after the closing delimiter.

Run a query foreach databases (mysql)

I'm looking for a straight way to run a query on all databases hosted on my mysql server.
I have a bunch of Magento installations and I want to truncate all Magento log table on all databases:
log_customer
log_visitor
log_visitor_info
log_url
log_url_info
log_quote
report_viewed_product_index
report_compared_product_index
report_event
catalog_compare_item
I think it something very easy to accomplish in mysql but I cannot find a straight answer/solution.
*UPDATE *
According to #Ollie Jones it is not possible to do it without a STORE PROCEDURE or a server side language ( PHP or whatever )
UPDATE 1
I choose to follow the PHP approach (#samitha) for 2 reasons:
STORE PROCEDURE looks more complicated
Query on 'information_schema' table is very slow ( at least if you have many DB/TABLES)
SELECT DISTINCT SCHEMA_NAME AS `database`
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql')
ORDER BY SCHEMA_NAME
gets you a list of all the non-MYSQL databases on your system.
SELECT TABLE_SCHEMA AS `database`,
TABLE_NAME AS `table`
FROM information_schema.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_SCHEMA, TABLE_NAME
gets you a list of all the actual tables (excluding SYSTEM VIEWs like the TABLES table, and user-defined views) in all the databases.
Then, you should implement logic in your program to ensure that, for each database, it really is a Magento database before you truncate certain tables. Otherwise, you might become a despised person among your co-workers. :-)
Edit
Here's a stored procedure.
You need to edit it to do exactly what you need it to do; in particular, it counts rows rather than truncating tables, and it doesn't contain the correct list of log tables. (It would be irresponsible for me to publish such a wildly destructive stored procedure; you should edit it yourself to do the destructive part.)
DELIMITER $$
DROP PROCEDURE IF EXISTS `zap_magento_logs`$$
CREATE PROCEDURE `zap_magento_logs`()
BEGIN
-- declare variables for database and table names
DECLARE dbname VARCHAR(128) DEFAULT '';
DECLARE tbname VARCHAR(128) DEFAULT '';
DECLARE done INTEGER DEFAULT 0;
-- declare cursor for list of log tables
DECLARE log_table_list CURSOR FOR
SELECT TABLE_SCHEMA AS `database`,
TABLE_NAME AS `table`
FROM `information_schema`.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME IN
(
'log_customer',
'log_visitor',
'log_visitor_info',
'log_url',
'log_url_info',
'log_quote'
)
ORDER BY TABLE_SCHEMA, TABLE_NAME;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET done = 1;
OPEN log_table_list;
log_table: LOOP
FETCH log_table_list INTO dbname, tbname;
IF done = 1 THEN
LEAVE log_table;
END IF;
-- create an appropriate text string for a DDL or other SQL statement
SET #s = CONCAT('SELECT COUNT(*) AS num FROM ',dbname,'.',tbname);
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP log_table;
CLOSE log_table_list;
END$$
DELIMITER ;
You run this by issuing the SQL command
CALL zap_magento_logs();
A PHP approach would be:
$tables = array(
'log_customer',
'log_visitor',
'log_visitor_info',
'log_url',
'log_url_info',
'log_quote',
'report_viewed_product_index',
'report_compared_product_index',
'report_event',
'catalog_compare_item',
);
$dbh = new PDO('mysql:host=localhost;', 'USERNAME', 'PASSWORD', array(
PDO::ATTR_PERSISTENT => true
));
$sql = $dbh->query('SHOW DATABASES');
$getAllDbs = $sql->fetchALL(PDO::FETCH_ASSOC);
foreach ($getAllDbs as $DB) {
foreach ($tables as $table) {
$dbh->query('TRUNCATE TABLE ' . $DB['Database'] . '.' . $table);
};
};
I didn't feel like writing code to solve this so I found a different solution. I wrote SQL that generates the SQL that I need. So I saved the following to a file called createSomeSQL.sql:
SET sql_mode='PIPES_AS_CONCAT';
select
'truncate table ' || dbs.database || '.someLogTable;'
as ''
from (SELECT DISTINCT SCHEMA_NAME AS `database`
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql', 'test')
ORDER BY SCHEMA_NAME) as dbs;
You could replace the SQL in line 4 with anything you want. Then I ran this command to generate the SQL that I need:
mysql -u root -p < createSomeSQL.sql > sqlToExecute.sql
Replace "root" with your username, of course. Now the file sqlToExecute.sql contains a script you can run to execute that SQL against all your databases.
Try the following (very basic, no error handling, may not work at all, I've not tested this):
$db = mysqli_connect(); // your database connection
$tables = ["log_customer", "log_visitor", "log_visitor_info"]; // array with all the tables
foreach ($tables as $table) {
mysqli_query($db, "TRUNCATE TABLE `".$table."`"); // executes query for each element in the array
}

How can you disable result output for the mysql EXECUTE command in workbench

I'm trying to use a prepared statement in mysql workbench in a cursor. The cursor works on a very big data set so it is executed many times. Every time a new result is shown for the EXECUTE step. This results eventually in mysql workbench crashing because of too many open result windows.
In the cursor I do something like this:
PREPARE stmt2 FROM #eveningQuery;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
Normally I use stuff like
set aVar = (EXECUTE stmt2);
to silence the query but EXECUTE doesn't work like that.
Does anybody know how you can disable the output for the EXECUTE command in mysql?
Note: I understand how i can retrieve the data in a variable, however what I want to prevent is that it is displayed in the results overview like this
This will make mysql-workbench crash when looped too much.
edit because it was asked an example of the #eveningQuery.
SET #eveningQuery = CONCAT('select #resultNm := exists (select idSplitBill from tb_SplitDay where idSplitBill =', idSplitBillVar, ' and ', #columnNameEv ,' = 1 and softdelete = 0)');
idSplitBillVar = the id coming from the cursor.
#columnNameEv = a column that i am filling in variably.
I added this info because it was asked, however it doesn't really matter in my opinion because the question still stands even with the most simple query. When you execute a prepared statement, you will get a output result. I just want to disable this behaviour.
The query you use creates new result-set, and GUI client show it (...many times) -
SELECT #resultNm:=EXISTS(
SELECT idSplitBill FROM tb_SplitDay
WHERE idSplitBill =', idSplitBillVar, ' AND ', #columnNameEv ,' = 1 AND softdelete = 0
)
You can rewrite this query, and result-set won't be created -
SELECT EXISTS(
SELECT idSplitBill FROM tb_SplitDay
WHERE idSplitBill =', idSplitBillVar, ' AND ', #columnNameEv ,' = 1 AND softdelete = 0
)
INTO #resultNm

How to echo print statements while executing a sql script

We have a simple sql script which needs to be executed against a MySQL database and we would like print log statements on the progress of the script (e.g. Inserted 10 records into foo or Deleted 5 records from bar). How do we do this?
I would like to know the syntax to be used for insert/update/delete statements.
How do I know about the number of rows affected by my statement(s).
I would also like to control printing them using a ECHO off or on command at the top of the script.
The script should be portable across Windows / Linux OS.
This will give you are simple print within a sql script:
select 'This is a comment' AS '';
Alternatively, this will add some dynamic data to your status update if used directly after an update, delete, or insert command:
select concat ("Updated ", row_count(), " rows") as '';
I don't know if this helps:
suppose you want to run a sql script (test.sql) from the command line:
mysql < test.sql
and the contents of test.sql is something like:
SELECT * FROM information_schema.SCHEMATA;
\! echo "I like to party...";
The console will show something like:
CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME
def information_schema utf8
def mysql utf8
def performance_schema utf8
def sys utf8
I like to party...
So you can execute terminal commands inside an sql statement by just using \!, provided the script is run via a command line.
\! #terminal_commands
Just to make your script more readable, maybe use this proc:
DELIMITER ;;
DROP PROCEDURE IF EXISTS printf;
CREATE PROCEDURE printf(thetext TEXT)
BEGIN
select thetext as ``;
END;
;;
DELIMITER ;
Now you can just do:
call printf('Counting products that have missing short description');
What about using mysql -v to put mysql client in verbose mode ?
For mysql you can add \p to the commands to have them print out while they run in the script:
SELECT COUNT(*) FROM `mysql`.`user`
\p;
Run it in the MySQL client:
mysql> source example.sql
--------------
SELECT COUNT(*) FROM `mysql`.`user`
--------------
+----------+
| COUNT(*) |
+----------+
| 24 |
+----------+
1 row in set (0.00 sec)
You can use print -p -- in the script to do this example :
#!/bin/ksh
mysql -u username -ppassword -D dbname -ss -n -q |&
print -p -- "select count(*) from some_table;"
read -p get_row_count1
print -p -- "select count(*) from some_other_table;"
read -p get_row_count2
print -p exit ;
#
echo $get_row_count1
echo $get_row_count2
#
exit