MySQL store checksum of tables in another table - mysql

CONTEXT:
we have big databases with loads of tables. Most of them (99%) are using innodb.
we want to have a daily process that monitors which table has been modified. As they use innodb the value of Update_time from
SHOW table STATUS from information_schema;
is null.
For that reason we want to create a daily procedure that will store the checksum (and other stuffs for that matters) of each table somewhere (preferably another table). On that, we will do different checks.
PROBLEM:
I'm trying to use
checksum table from db_schema.table_name;
which returns a resultset-table with 2 columns: "table","checksum".
It gives me the value I want but I'm not able to use it in a select or insert statement.
I tried a lot of things like:
select `checksum` from (checksum table from db_schema.table_name);
or other similar queries. But I'm not able to extract the data from the resultset.
Is there a way I can do that?
Thanks in advance for your help.
EDIT: in the end what I want is to build a more complex resultset having different informations in it (table schema, table name, count, checksum, datetime:now()...)
Then I'll use this resultset to compare with the values of yesterday and draw my own statistics. That's why I want to get the checksum from that resultset.

There is no possibility to save the result of CHECKSUM TABLE directly using SQL. Neither can you use prepared statements or cursors in stored procedures to use the checksum result.
You best make a script around it, or download some popular tools doing it for you.
For MyISAM tables using the CHECKSUM=1 table argument, you can simply use INFORMATION_SCHEMA like this:
SELECT TABLE_NAME,CHECKSUM FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test' AND ENGINE='MyISAM'
AND CHECKSUM IS NOT NULL;

Related

Run an ALTER TABLE across all like tables (containing the same schema) in MySQL database

I have a database that contains a table per client, each table has the same columns in them. We're talking a few thousand client tables.
I need to add new columns to each of these tables for new development but cannot find a way to recurse all the tables in the database to add the columns. I know MS SQL has something sp_MSforeachtable which does maybe what I'm asking but I don't know if MySQL has anything similar?
As per this previous answer in SO you could do something like this :
select concat('ALTER TABLE `',table_name,'` ADD `test` INT NOT NULL AFTER `column_x`;')
from information_schema.tables
where table_schema = 'your_db_name'
Then remove the few tables not about client (here's hoping client is the only entity to have "private table") or if possible add a condition on the table_name (like AND table_name LIKE "client_%"), and execute the whole batch.
The 2nd solution, to use procedure, is too complex (for me) for this use case, but maybe someone more skilled than me in PLSQL won't agree.

Using a pre made sql query to get table structure

I'm rather new at database management, so this might not be feasible, but I got a handful of SQL select queries, rather long ones at that. What I'd like is to get the table column names and structure, without access to the actual database, so as to get a map of all this queries.
context: All we have are the queries used to output tables that will be given to us latter.
This need not be done with actual SQL code, maybe a short script in other language or a utility somebody knows of (but I do have MySQL workbench)
You can add a CREATE TABLE statement in front of your select queries to get the column names.
You cannot infer data types or keys from select queries.
For column names do something like:
drop table if exists your_table_name;
create table your_table_name
select *
from ...
where the select * portion is replaced by the select queries you have.
Then to see the column names in a friendlier way you can do:
show create table your_table_name;
or
desc your_table_name;

MySQL - Trigger or Replication is better?

I want to replicate certain table from one database into another database in the same server. This tables contain exactly the same fields.
I was considering to use MySQL Replication to replicate that table but some people said that it will increase IO so i find another way to create 3 Trigger (Insert, update and Delete) that will perform exactly the same thing like what i expect.
My Question is, which way is better? Is it using MySQL replication is better even though it's in the same server or using Trigger to replicate the data is better.
Thanks.
I don't know what is your goal, but I got mine getting use of the VIEW functionality.
I had two different applications with separate databases but in the same Mysql server. Application2 needed to get a few data from Application1. In general, this is a trivial situation that you can handle with USE DB1; or USE DB2; as your needing, but my programming framework does not work very well with multiple DBs.
So, lets see my solution...
Here is my select query to retrieve this data:
SELECT id, name FROM DB1.customers;
So, using DB2 as default schema, I've created a VIEW:
USE DB2;
CREATE VIEW app1_customers AS SELECT id, name FROM DB1.customers;
Now I can retrieve this data in DB2 as a regular table with a regular SELECT statement.
SELECT * FROM DB2.app1_customers;
Hope ts useful. BR
Assuming you have two databases on the same server i.e DB1 and DB2 and the table is called tbl1 and it is sitting in DB1 you can query the table like this:
USE DB1;
SELECT * FROM tbl1;
USE DB2;
SELECT * FROM DB1.tbl1;
This way you wont need to copy the data and worry about extra space and extra code. You can query a table in another database on the same server. Replication and triggers are not your answer here. You could also create a view to encapsulate the SQL statement.
Definitely triggers is the way to go. Having another server (slave) will need to spare several MB for installation, logs, cpu and memory usage.
I'd use triggers to keep both tables equal. If you want to create a table with the same columns definition and data use:
USE db2;
CREATE TABLE t1 AS SELECT * FROM db1.t1;
After that, go ahead and create the triggers for Update, Insert and Delete statemetns.
Also you could ALTER the new table to a different engine like MEMORY or add indexes to see if you can improve something.

Can I INSERT/UPDATE into two tables with one query?

Here is a chunk of the SQL I'm using for a Perl-based web application. I have a number of requests and each has a number of accessions, and each has a status. This chunk of code is there to update the table for every accession_analysis that shares all these fields for each accession in a request.
UPDATE accession_analysis
SET analysis_id = ? ,
reference_id = ? ,
status = ? ,
extra_parameters = ?
WHERE analysis_id = ?
AND reference_id = ?
AND status = ?
AND extra_parameters = ?
and accession_id is (
SELECT accesion_id
FROM accessions
where request_id = ?
)
I have changed the tables so that there's a status table for accession_analysis, so when I update, I update both accession_analysis and accession_analysis_status, which has status, status_text and the id of the accession_analysis, which is a not null auto_increment variable.
I have no strong idea about how to modify this code to allow this. My first pass grabbed all the accessions and looped through them, then filtered for all the fields, then updated. I didn't like that because I had many connections with short SQL commands, which I understood to be bad, but I can't help but think the only way to really do this is to go back to the loop in Perl holding two simpler SQL statements.
Is there a way to do this in SQL that, with my relative SQL inexperience, I'm just not seeing?
The answer depends on which DBMS you're using. The easiest way is to create a trigger on one table that provides the logic of updating the other table. (For any DB newbies -- a trigger is procedural code attached to a table at the DBMS (not application) layer that runs in response to an insert, update or delete on the table.). A similar, slightly less desirable method is to put the logic in a stored procedure and execute that instead of the update statement you're now using.
If the DBMS you're using doesn't support either of these mechanisms, then there isn't a good way to do what you're after while guaranteeing transactional integrity. However if the problem you're solving can tolerate a timing difference in the two tables' updates (i.e. The data in one of the tables is only used at predetermined times, like reporting or some type of batched operation) you could write to one table (live) and create a separate process that runs when needed (later) to update the second table using data from the first table. The correctness of allowing data to be updated at different times becomes a large and immovable design assumption, however.
If this is mostly about connection speed, then one option you have is to write a stored procedure that handles the "double update or insert" transparently. See the manual for stored procedures:
http://dev.mysql.com/doc/refman/5.5/en/create-procedure.html
Otherwise, You probably cannot do it in one statement, see the MySQL INSERT syntax:
http://dev.mysql.com/doc/refman/5.5/en/insert.html
The UPDATE syntax allows for multi-table updates (not in combination with INSERT, though):
http://dev.mysql.com/doc/refman/5.5/en/update.html
Each table needs its own INSERT / UPDATE in the query.
In fact, even if you create a view by JOINing multiple tables, when you INSERT into the view, you can only INSERT with fields belonging to one of the tables at a time.
The modifications made by the INSERT statement cannot affect more than one of the base tables referenced in the FROM clause of the view. For example, an INSERT into a multitable view must use a column_list that references only columns from one base table. For more information about updatable views, see CREATE VIEW.
Inserting data into multiple tables through an sql view (MySQL)
INSERT (SQL Server)
Same is true of UPDATE
The modifications made by the UPDATE statement cannot affect more than one of the base tables referenced in the FROM clause of the view. For more information on updatable views, see CREATE VIEW.
However, you can have multiple INSERTs or UPDATEs per query or stored procedure.

How to retrieve MYSQL records as an INSERT statement

I'm trying come up with the best method of synchronizing particular rows of 2 different database tables. So, for example there's 2 product tables in different databases as such...
Origin Database
product{
merchant_id,
product_id,
... additional fields
}
Destination Database
product{
merchant_id
product_id
... additional fields
}
So, the database schema is the same for both. However I'm looking to select records with a particular merchant_id, remove all records from the destination table that have that merchant_id and replace those records with records from the origin database of the same merchant_id.
My first thought was using mysqldump, parsing out the create table statements, and only running the Insert Statements. Seems like a pain though. So I was wondering if there is a better technique to do this.
I would think mysql has some method of creating INSERT statements as output from a SELECT statement, so you can define how to insert specific record information into a new db.
Any help would be appreciated, thank you much.
phpMyAdmin has part of this capability: You can run a query and then export the results of that query into a file containing CREATE statements.
Update: And mysqldump has it too: Link
mysqldump -u username -p --where="id='merchant_id'" databasename
In regards to replacing merchant IDs, that part I don't entirely understand yet. You may be better off doing a manual search+replace on them. Can you make a real life example of two such records?