There is a way to write data to disk from a trigger into a file? The file name need to be created dynamically.
Using PREPARE will not work on trigger.
e.g.
SET #Query1 =
CONCAT("SELECT ",'data'," INTO DUMPFILE 'c:/temp/", UNIX_TIMESTAMP(),"-",RAND(), ".txt'");
PREPARE statementCreate FROM #Query1;
EXECUTE statementCreate;
DEALLOCATE PREPARE statementCreate;
Note: data is a variable
Or there is other solution to append to the same file from the trigger? Will work that too.
MySQL documentation says:
SQL prepared statements (PREPARE, EXECUTE, DEALLOCATE PREPARE)
can be used in stored procedures, but not stored functions or triggers.
Thus, stored functions and triggers cannot use dynamic SQL
(where you construct statements as strings and then execute them).
So no - you can't write data to file which name is dynamically created from a trigger.
Since you can't use dynamic sql but you also approve single file name and append data to it you can load data to temporary file, append results of the query and then output full results to a file. Of course it will work only if there is no other need to use dynamically created query except file name.
On example:
DELIMITER $$
CREATE TRIGGER rewrite_file AFTER INSERT tableName
BEGIN
CREATE TEMPORARY TABLE IF NOT EXISTS temp(
pk BIGINT
);
LOAD DATA INFILE 'c:/somefile.txt' INTO TABLE temp
LINES TERMINATED BY '\n';
INSERT INTO temp (pk) SELECT primaryKeyField FROM tableName;
SELECT pk INTO OUTFILE 'c:/somefile.txt'
LINES TERMINATED BY '\n'
FROM temp;
END$$
DELIMITER ;
It will append file c:/somefile.txt on every insert. Of course this solution sucks if your file grows to millions of entries.
The solution is: MySQL UDF:http://www.mysqludf.org.
I install sys_exec function and after that from trigger I have something like
SET #ret_val = sys_exec(CONCAT('echo.>d:/temp/',NEW.id, '-', UNIX_TIMESTAMP() , '.txt'));
This will create a empty file for each insert. Tested on windows and linux(CentOS).
Related
I want to take database script backup every day using event in mySql ..I am new to mySql , so unable to find out exact solution..can anybody help me to do so??
Tried it using mysqldump utility but it is command promt oriented , i want it to be done through event scheduler only.
DELIMITER $$
create EVENT `Backup`
ON SCHEDULE EVERY 1 minute
STARTS '2016-02-25 17:08:06' ON COMPLETION PRESERVE ENABLE
DO
BEGIN
SET #sql_text = CONCAT("SELECT * FROM purpleaid INTO OUTFILE '/C:/Users/Admin123/Desktop/db/" , DATE_FORMAT( NOW(), '%Y%m%d') , "db.csv'" );
PREPARE s1 FROM #sql_text;
EXECUTE s1;
DEALLOCATE PREPARE s1;
END $$
DELIMITER ;
tried this , but its for single table only.I want complete database script
You can use information_schema.tables table to get list of tables within a database, and information_schema.columns table to get list of columns (just in case you want to have column names included in the backup files).
Create a cursor by getting all table names from your database
Loop through the cursor and get the table name into a variable
Construct your select ... into outfile ... statements the same way as you do in your current code, just add the table name from the variable.
Execute the prepared statement.
If you want to add the column names dynamically to the output, then combine Joe's and matt's answers from this SO topic.
UPDATE
For views, stored procedures, functions, and triggers (and tables, for that matter) the issue is that you can't really interact with show create ... statements' results within sql. You can try to recreate their definitions from their respective information_schema tables, but as far as I know, it is not possible to fully reconstruct each object just based on these tables. You need to use an external tool for that, such us mysqldump. If you want a full backup option, then you would be a lot better off, if you used an external tool, that is scheduled by the OS' task scheduler.
Since table structures and other database objects do not change that often (at least, not in production), you can use external tool to back up the structure and use the internal scheduled script to regularly back up the contents.
I have a database to which several real users have access using JDBC. The separation of these users is very crucial, such that they are neither able see nor manipulate each other's data.
To separate the users' data, I decided to create the few corresponding tables for every user, and only give the owning user the permissions on this table. This is all done automatically in a stored procedure.
Besides this table separation, I want a user only to execute stored procedures to work with his tables, not arbitrary SQL queries.
Let's consider an example procedure like
DELIMITER //
CREATE PROCEDURE MyProcedure(IN p_identifier VARCHAR(30), IN p_key INT(10))
BEGIN
SET #p_identifier = p_identifier;
SET #p_key = p_key;
SET #s = CONCAT('DELETE FROM ', p_identifier, '_mytable WHERE key =?;');
PREPARE stmt FROM #s;
EXECUTE stmt USING #p_key,
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
And use it like CALL MyProcedure('ad3e981b', 2);.
So far, so good.
Problems arise since this procedure is used by all users (the first paraeter is the table-prefix). This is bad, because once a user gets execution privileges for MyProcedure, he is able to to provide any table-prefix at will and mess with other user's data - so my user separation is gone. This is the problem I need to solve.
I currently see two solutions:
Don’t use stored procedures: Just give INSERT/DELETE/SELECT privileges on the user's table only to the user. This is simple and works - but I'd prefer to only call stored procedures over JDBC, not arbitrary SQL queries.
Make a stored procedure for EVERY user, in which the table prefix is invariant (e.g, table-prefix_MyProcedure(), which is only executable by one user). Then, assign the execution privilege only to the corresponding user. However, this should be done automatically on request - hence, I need to be able to create a stored procedure with a parameterized name to set this up (phew). As the title suggests, this is the way I want to go - but I really struggle with the syntax of dynamically creating a stored procedure (in a stored procedure) and thus, I'm really not sure if this is how I should proceed.
Any ideas how I got approach this problem?
Regards,
raute
First I tried this, (MySQL/phpmyadmin)
CREATE DEFINER=`root`#`localhost` PROCEDURE `tempcheck`() NO SQL
BEGIN
SET #query_string = 'SELECT * FROM properties';
PREPARE query_statement FROM #query_string;
EXECUTE query_statement;
DEALLOCATE PREPARE query_statement;
END
This just fetches the first record of the table 'properties'. The table has more than one value. When I sqlquery 'select * from properties;' it returns the whole table.
I even tried this simple method
BEGIN
SELECT * FROM properties';
END
Tried many stackoverflow Q&As. They all suggest that I make a temp table. Even if I do, how will it return the whole table when it doesn't return the entire table here in the first place. CAN a mysql stored procedure actually return a whole table or NOT. if it can, then how?
Guys thank you all for your help. One of my colleagues helped me fix it. Apparently it's a bug in phpmyadmin. phpmyadmin won't return more than one record
i want to create a table and append NOW() to the end of the table name.
what would be the syntax please?
oops thank you for the correction.
My reason why i wat to do this is i have a script that runs on the database table everyday. If certain conditions are met i delete from the master table. BUT before i delete i just want to make a backup copy by running: create table rc_profile_backup_table_NOW() like rc_profile_table;
then i run: insert rc_profile_table_backup_NOW() select * from rc_profile_table
hope this is better.
thanks
Here is some rather ugly way to do it, using prepared statements. You might adjust the "now" part, because now makes invalid tables names I think.
set #c=concat('create table zogi_',date_format(now(),'%Y_%m_%d'),' (a varchar(10))');
prepare stmt from #c;
execute stmt;
deallocate prepare stmt
describe zogi_2012_02_07;
It creates a table named zogi_[year][month][day].
I am trying to write a simple stored procedure which will clear the contents of some tables in the current database - I'm doing this by matching a prefix against the list of tables in the information_schema:
delimiter $$
create procedure local_flush_cache(db varchar(255))
begin
select #str_sql:=concat('delete from ',group_concat(table_name))
from information_schema.tables
where table_schema=db and table_name like 'cache_%';
prepare stmt from #str_sql;
execute stmt;
drop prepare stmt;
end$$
delimiter ;
I would like to be able to remove the db parameter and have the function work on the currently active database.
I guess I will also need the ability to recognise that a database has not yet been selected and output an error (to prevent accidentally flushing all cache tables in all databases).
Considering that the procedure is tied to a database, the current is the called unless you do CALL db.proc().
However, if you really want the selected one, you can the DATABASE() function:
where table_schema=database() and table_name like 'cache_%';