I'm creating a function in mySQL that will update table metrics each time the any table has something inserted or deleted from it. So I've got my Table_metrics table, with elements table_name and row_count:
CREATE TABLE Table_metrics (
table_name VARCHAR(64),
row_count INTEGER DEFAULT 0 );
So any time something gets added to any of my tables (other than this one) in the database the matching row gets updated with the number of rows in that table.
To do this I've tried making a stored procedure:
CREATE PROCEDURE table_update_metric(IN tablename VARCHAR(64))
UPDATE Table_metrics
SET row_count=(SELECT COUNT(*) FROM tablename)
WHERE table_name = tablename;
This produces an error when I call the procedure call table_update_metric('Owners'); (Owners being a table in my database)
table DB.tablename doesn't exist
I've done a bit of digging into stored procedures, trying to figure out how they would work. I assume the issue is coming from the line `SELECT COUNT(*) FROM tablename), so I tried having a stored statement in the procedure:
CREATE PROCEDURE table_update_metric(IN TABLENAME VARCHAR(64))
SET #s = CONCAT('SELECT COUNT(*) FROM ', tablename)
UPDATE Table_metrics
SET row_count=EXECUTE #s
WHERE table_name = tablename;
I'm not really sure how to properly do a stored statement as I'm still relatively new to mySQL, but I believe that it's the way to go.
Can anyone offer any insight into this problem?
What you are trying to do is already provided in Mysql. Information Schema Tables stores this information for you :)
SELECT TABLE_NAME, TABLE_ROWS)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '{your_db}';
From what Somonare said, I created a table in my database that uses that information:
CREATE TABLE Table_metrics
SELECT TABLE_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'Sensors';
And this table will be updated with a trigger each time the tables in Sensors are updated.
This is the query i am using:
IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME =( N'CustomerVariable1Value'))
begin Alter table temp.DIM_BE_ACCOUNT drop column CustomerVariable1Value
It works fine the first time but when I run it again, it shows error.
How to make it error free and executes it many number of times?
Error message:
ALTER TABLE DROP COLUMN failed because column 'CustomerVariable1Value' does not exist in table 'DIM_BE_ACCOUNT'.
You are only looking for a column name out of all column names in the entire MySQL instance. You need to also filter by schema (=database) and table names:
IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = N'CustomerVariable1Value' AND TABLE_NAME = 'MyTableName' AND TABLE_SCHEMA = 'MyDatabase')
Here is a solution that does not involve querying INFORMATION_SCHEMA, it simply ignores the error if the column does not exist.
DROP PROCEDURE IF EXISTS `?`;
DELIMITER //
CREATE PROCEDURE `?`
(
)
BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
ALTER TABLE `table_name` DROP COLUMN `column_name`;
END //
DELIMITER ;
CALL `?`();
DROP PROCEDURE `?`;
P.S. Feel free to give it other name rather than ?
I want to update a MySQL database schema (with MySQL code) but I am unfortunately not sure of the state of the tables, as they are distributed..
Let's say some 'clients' have a table called "user" with a schema like
name VARCHAR(64) NOT NULL
password VARCHAR(64) NOT NULL
I want to add an email column, but it's possible that they already have an email column (depending on their installation version).
How can I run a command that ensures that there is a email column and does nothing if it's already there? Keep in mind I would be doing this for many tables that are more complex.
I know I could be creating temp tables and re-populating (and will if it's the only solution) but I figure there might be some kind of CREATE or UPDATE table command that has "oh you already have that column, skip" logic.
You can try like this:
DELIMITER $$
CREATE PROCEDURE Alter_MyTable()
BEGIN
DECLARE _count INT;
SET _count = ( SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'user' AND
COLUMN_NAME = 'email');
IF _count = 0 THEN
ALTER TABLE user
ADD COLUMN email varchar(512);
END IF;
END $$
DELIMITER ;
or rather make it a generic stored procedure like this:
create procedure AddColumnIfDoesntExists(
IN dbName tinytext,
IN tableName tinytext,
IN fieldName tinytext,
IN fieldDef text)
begin
IF NOT EXISTS (
SELECT * FROM information_schema.COLUMNS
WHERE column_name=fieldName
and table_name=tableName
and table_schema=dbName
)
THEN
set #ddl=CONCAT('ALTER TABLE ',dbName,'.',tableName,
' ADD COLUMN ',fieldName,' ',fieldDef);
prepare stmt from #ddl;
execute stmt;
END IF;
end;
//
delimiter ';'
If the column already exists the ALTER TABLE ADD COLUMN statement will throw an error, so if you are thinking that you might lose data because of trying to add a column that already exists that won't be the case, if any you need to handle error. See add column to mysql table if it does not exist
There are also resources telling you how to deal with these with store procedures, etc. See MySQL add column if not exist.
Hope it helps.
I have a lot of delete queries but in some production databases some table is not found. I need simple decision on this problem.
Queries like
DELETE b.* FROM `table` b
JOIN `another_table` u
ON u.key2 = b.key
WHERE u.key3 <> ?
I need something like:
IF TABLE `table` EXISTS DELETE b.* FROM `table` b ...
If you need to delete the rows of a table if that latter exists, you will have to rely on a custom stored procedure I think. something like that:
-- Define the procedure
CREATE PROCEDURE delete_if_exists(IN tbl CHAR(80))
BEGIN
IF #tbl IN (select table_name from information_schema.tables where table_schema = "db_2_44afb7")
THEN
SET #query = CONCAT("DELETE FROM ", #tbl);
PREPARE stmt FROM #query;
EXECUTE stmt;
END IF;
END //
-- use it
CALL delete_if_exists("mytable");
CALL delete_if_exists("myothertable");
See http://sqlfiddle.com/#!2/2ee190/3 for an example.Of course, you could adjust the "DELETE FROM",... part to fit with your specific needs.
You can enclose the SELECT query on the table before using the DROP...
IF EXISTS(SELECT table.records FROM table WHERE ...)
DELETE records_names FROM ...
From what it sounds like IF EXISTS(select query here) before your delete command is what you're looking for? I'm a postgresql guy so please excuse the SQL errors if they exist.
More examples in this post.
How do I copy or clone or duplicate the data, structure,
and indices of a MySQL table to a new one?
This is what I've found so far.
This will copy the data and the structure,
but not the indices:
create table {new_table} select * from {old_table};
This will copy the structure and indices,
but not the data:
create table {new_table} like {old_table};
To copy with indexes and triggers do these 2 queries:
CREATE TABLE new_table LIKE old_table;
INSERT INTO new_table SELECT * FROM old_table;
To copy just structure and data use this one:
CREATE TABLE new_table AS SELECT * FROM old_table;
I've asked this before:
Copy a MySQL table including indexes
Apart from the solution above, you can use AS to make it in one line.
CREATE TABLE tbl_new AS SELECT * FROM tbl_old;
MySQL way:
CREATE TABLE recipes_new LIKE production.recipes;
INSERT recipes_new SELECT * FROM production.recipes;
Go to phpMyAdmin and select your original table then select "Operations" tab in the "Copy table to (database.table)" area. Select the database where you want to copy and add a name for your new table.
I found the same situation and the approach which I took was as follows:
Execute SHOW CREATE TABLE <table name to clone> : This will give you the Create Table syntax for the table which you want to clone
Run the CREATE TABLE query by changing the table name to clone the table.
This will create exact replica of the table which you want to clone along with indexes. The only thing which you then need is to rename the indexes (if required).
The better way to duplicate a table is using only DDL statement. In this way, independently from the number of records in the table, you can perform the duplication instantly.
My purpose is:
DROP TABLE IF EXISTS table_name_OLD;
CREATE TABLE table_name_NEW LIKE table_name;
RENAME TABLE table_name TO table_name_OLD;
RENAME TABLE table_name _NEW TO table_name;
This avoids the INSERT AS SELECT statement that, in case of table with a lot of records can take time to be executed.
I suggest also to create a PLSQL procedure as the following example:
DELIMITER //
CREATE PROCEDURE backup_table(tbl_name varchar(255))
BEGIN
-- DROP TABLE IF EXISTS GLS_DEVICES_OLD;
SET #query = concat('DROP TABLE IF EXISTS ',tbl_name,'_OLD');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- CREATE TABLE GLS_DEVICES_NEW LIKE GLS_DEVICES;
SET #query = concat('CREATE TABLE ',tbl_name,'_NEW LIKE ',tbl_name);
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- RENAME TABLE GLS_DEVICES TO GLS_DEVICES_OLD;
SET #query = concat('RENAME TABLE ',tbl_name,' TO ',tbl_name,'_OLD');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- RENAME TABLE GLS_DEVICES_NEW TO GLS_DEVICES;
SET #query = concat('RENAME TABLE ',tbl_name,'_NEW TO ',tbl_name);
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END//
DELIMITER ;
Have a nice day!
Alex
To duplicate a table and its structure without data from a different a database use this. On the new database sql type
CREATE TABLE currentdatabase.tablename LIKE olddatabase.tablename
Worths to mention the importance of checking if the table already exists before
trying to duplicate it:
CREATE TABLE IF NOT EXISTS new_table LIKE old_table;
INSERT new_table
SELECT * FROM old_table;
As was said by the previous answers this will copy structure, data and
all the dependent objects of the table.
See MySql Tutorial:
Expanding on this answer one could use a stored procedure:
CALL duplicate_table('tableName');
Which will result in a duplicate table called tableName_20181022235959 If called when
SELECT NOW();
results:
2018-10-22 23:59:59
Implementation
DELIMITER $$
CREATE PROCEDURE duplicate_table(IN tableName VARCHAR(255))
BEGIN
DECLARE schemaName VARCHAR(255) DEFAULT SCHEMA();
DECLARE today VARCHAR(14) DEFAULT REPLACE(REPLACE(REPLACE(NOW(), '-', ''), ' ', ''), ':', ''); -- update # year 10000
DECLARE backupTableName VARCHAR(255) DEFAULT CONCAT(tableName, '_', today);
IF fn_table_exists(schemaName, tableName)
THEN
CALL statement(CONCAT('CREATE TABLE IF NOT EXISTS ', backupTableName,' LIKE ', tableName));
CALL statement(CONCAT('INSERT INTO ', backupTableName,' SELECT * FROM ', tableName));
CALL statement(CONCAT('CHECKSUM TABLE ', backupTableName,', ', tableName));
ELSE
SELECT CONCAT('ERROR: Table "', tableName, '" does not exist in the schema "', schemaName, '".') AS ErrorMessage;
END IF;
END $$
DELIMITER ;
DELIMITER $$
CREATE FUNCTION fn_table_exists(schemaName VARCHAR(255), tableName VARCHAR(255))
RETURNS TINYINT(1)
BEGIN
DECLARE totalTablesCount INT DEFAULT (
SELECT COUNT(*)
FROM information_schema.TABLES
WHERE (TABLE_SCHEMA COLLATE utf8_general_ci = schemaName COLLATE utf8_general_ci)
AND (TABLE_NAME COLLATE utf8_general_ci = tableName COLLATE utf8_general_ci)
);
RETURN IF(
totalTablesCount > 0,
TRUE,
FALSE
);
END $$
DELIMITER ;
DELIMITER $$
CREATE PROCEDURE statement(IN dynamic_statement TEXT)
BEGIN
SET #dynamic_statement := dynamic_statement;
PREPARE prepared_statement FROM #dynamic_statement;
EXECUTE prepared_statement;
DEALLOCATE PREPARE prepared_statement;
END $$
DELIMITER ;
After I tried the solution above, I come up with my own way.
My solution a little manual and needs DBMS.
First, export the data.
Second, open the export data.
Third, replace old table name with new table name.
Fourth, change all the trigger name in the data (I use MySQL and it show error when I don't change trigger name).
Fifth, import your edited SQL data to the database.
To create table structure only use this below code :
CREATE TABLE new_table LIKE current_table;
To copy data from table to another use this below code :
INSERT INTO new_table SELECT * FROM current_table;
Simple Cloning:
it create a table from another table without taking into account any column attributes and indexes.
CREATE TABLE new_table SELECT * FROM original_table;
Shallow Cloning:
This will only create an empty table base on the structure of the original table
CREATE TABLE new_table LIKE original_table;
The following command would create an empty table base on the original table.
CREATE TABLE adminUsers LIKE users;
Deep Cloning:
This means the new table gets to have all the attributes of each column and indexes of the existing table. This quite useful if you want to maintain the indexes and attributes of the existing table.
CREATE TABLE new_table LIKE original_table;
INSERT INTO new_table SELECT * FROM original_table;
https://towardsdatascience.com/how-to-clone-tables-in-sql-dd29586ec89c
// To copy specific column data use this one:
CREATE TABLE ut_axis_existrec LIKE ut_karvy_annexure; // To create new table
INSERT INTO ut_axis_existrec
(funding_ac,micr_no, warrant_no,
amount,invname,mfundcode,funding_dt,status,remarks1,amc_remark,created_at)
SELECT
t1.funding_ac,
t1.micr_no,
t1.warrant_no,
t1.amount,
t1.invname,
t1.mfund_code,
t1.funding_dt,
t1.status,
t1.remarks1,
t1.created_at
from ut_axis_karvy
inner join
ut_axis_karvy_master as t2
on t1.micr_no = t2.micr_no;
Try this :
`CREATE TABLE new-table (id INT(11) auto_increment primary key) SELECT old-table.name, old-table.group, old-table.floor, old-table.age from old-table;`
I selected 4 columns from old-table and made a new table.
FOR MySQL
CREATE TABLE newtable LIKE oldtable ;
INSERT newtable SELECT * FROM oldtable ;
FOR MSSQL
Use MyDatabase:
Select * into newCustomersTable from oldCustomersTable;
This SQL is used for copying tables, here the contents of oldCustomersTable will be copied to newCustomersTable.
Make sure the newCustomersTable does not exist in the database.