将数据从 MySQL table 传输到另一个 table
Transfer data from MySQL table to a different table
我在我的计算机上有一个数据库,我们就简单地称它为 'db',其中有一些 table 具有多个列,并且在 table 中包含数据。
我有一个软件使用这个数据库来存储配置元素和其他一些东西。
现在,我发布了我的软件的新版本,只对数据库进行了细微的修改,即一些列可能已添加到 tables 或删除(但没有重命名列)。
我必须保留所有数据,所以我想将其转移到我的数据库的新"version"。
我想到的:
- 将 'db' 重命名为 'db_old'。
- 将新数据库安装为 'db_new',并在新列中使用默认值
- 对于每个 table,获取 'db_old' 中存在于 'db_new'
中的所有列的列表
- 使用 INSERT INTO ... SELECT 将旧内容放回 'db_new'。
- 删除旧数据库并使用我的新数据库。
你觉得可行吗?你有什么简单的解决办法吗?
此外,我绝对不是 SQL 专家...我尝试了这个(没有查看该列是否已被删除):
SELECT
GROUP_CONCAT(COLUMN_NAME
SEPARATOR ',')
INTO @colList FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = 'db_old'
AND TABLE_NAME = 'configuration';
INSERT
INTO db_new.configuration (SELECT @colList)
SELECT @colList FROM
db_old.configuration;
但是用有效列表替换第二个@colList 失败...你能帮我解决这个问题吗?
谢谢大家,祝大家有个愉快的一天!
您应该首先转储 DB 数据库并创建一个 .sql 文件。根据您的数据库数据,此文件甚至可以以 GB 为单位。此 SQL 文件将包含您的所有表格以及这些表格中的所有数据。我建议您打开并查看该文件。
然后您应该使用这个新创建的文件并将所有数据导入新数据库。它会将所有这些表和数据放入这个新数据库中。
这是如何做到这一点。首先创建 SQL 文件:
mysqldump -h [SeverIpAddress] -u [UserName] -p[password] YourDbname > db_backup.sql
在远程服务器的情况下使用 -h [SeverIpAddress]。万一它在您自己的系统中重新启动,您不需要使用它。
然后您应该创建新的数据库,比方说 DB_new。创建后,使用 use 命令切换到它。
use DB_new
完成后,现在导入我们在使用 source 命令之前创建的 .SQl 文件。
source YourSQLFilePath
在你的情况下,source db_backup.sql
好的。如果有人遇到同样的问题,这里是解决方案。
首先,承认您有一个名为 'myDatabase' 的数据库,其中有一个名为 'myTable' 的 table 您想要 "upgrade",即您想要修改 table 按 adding/removing 列结构,但将数据保留在内部。
第一步是删除外键(如果有的话)并重命名 "myTable" :
USE `myDatabase`;
ALTER TABLE `myTable` DROP FOREIGN KEY `my_fk_constraint`;
ALTER TABLE `myTable` RENAME TO `old_myTable`;
第二步是导入新的 table 结构,例如使用 SOURCE。
SOURCE C:/new_table_structure.sql
第三步是可选的,但如果您的 table 有很多列,则可能需要此步骤:
USE `myDatabase`;
SET GLOBAL group_concat_max_len = 4294967295;
第四步是存储以下例程:
delimiter //
DROP PROCEDURE IF EXISTS updateConf//
CREATE PROCEDURE updateConf(IN dbName TEXT, IN old_table TEXT, IN new_table TEXT, IN primary_key_name TEXT)
BEGIN
-- get column count in old table
SELECT count(*)
INTO @colNb
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = dbName
AND TABLE_NAME = old_table;
-- get string with all column names from old_table
SELECT GROUP_CONCAT(COLUMN_NAME)
INTO @colNames1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = dbName
AND TABLE_NAME = old_table;
SET @colNames1 = CONCAT(@colNames1, ',');
-- get string with all column names from new_table
SELECT GROUP_CONCAT(COLUMN_NAME)
INTO @colNames2
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = dbName
AND TABLE_NAME = new_table;
-- variables initialization
SET @cpt = 1; -- column number counter
SET @pos = 1; -- position of column name first char
SET @vir = 1; -- next comma position
-- start of loop
label: LOOP
IF @cpt <= @colNb THEN
SET @vir = LOCATE(',',@colNames1,@pos); -- localize next comma
SET @colName = SUBSTRING(@colNames1, @pos, @vir - @pos); -- get column name
SET @pos = @vir + 1; -- update next column position
-- if column is in both tables
IF FIND_IN_SET(@colName, @colNames2) AND @colName != primary_key_name THEN
SET @execut = CONCAT("INSERT INTO ", new_table, " (", primary_key_name, ",", @colName, ") SELECT ", primary_key_name, ",", @colName, " FROM ", old_table, " ON DUPLICATE KEY UPDATE ", new_table, ".", @colName, " = ", old_table, ".", @colName);
PREPARE stmt FROM @execut;
EXECUTE stmt;
END IF;
SET @cpt = @cpt + 1; -- counter increment
-- when all columns parsed
ELSE
LEAVE label; -- end of loop
END IF;
END LOOP label;
END //
delimiter ;
最后一步是在 table 上调用过程,并删除临时 table:
CALL updateConf( 'myDatabase', 'old_myTable', 'myTable', 'primaryKeyName' );
DROP TABLE `old_myTable`;
瞧!只是不要忘记放回您删除的外键:)
当然可以用更好的方法来完成,但我让它正常工作。
谢谢大家!
我在我的计算机上有一个数据库,我们就简单地称它为 'db',其中有一些 table 具有多个列,并且在 table 中包含数据。 我有一个软件使用这个数据库来存储配置元素和其他一些东西。
现在,我发布了我的软件的新版本,只对数据库进行了细微的修改,即一些列可能已添加到 tables 或删除(但没有重命名列)。
我必须保留所有数据,所以我想将其转移到我的数据库的新"version"。
我想到的:
- 将 'db' 重命名为 'db_old'。
- 将新数据库安装为 'db_new',并在新列中使用默认值
- 对于每个 table,获取 'db_old' 中存在于 'db_new' 中的所有列的列表
- 使用 INSERT INTO ... SELECT 将旧内容放回 'db_new'。
- 删除旧数据库并使用我的新数据库。
你觉得可行吗?你有什么简单的解决办法吗?
此外,我绝对不是 SQL 专家...我尝试了这个(没有查看该列是否已被删除):
SELECT
GROUP_CONCAT(COLUMN_NAME
SEPARATOR ',')
INTO @colList FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = 'db_old'
AND TABLE_NAME = 'configuration';
INSERT
INTO db_new.configuration (SELECT @colList)
SELECT @colList FROM
db_old.configuration;
但是用有效列表替换第二个@colList 失败...你能帮我解决这个问题吗?
谢谢大家,祝大家有个愉快的一天!
您应该首先转储 DB 数据库并创建一个 .sql 文件。根据您的数据库数据,此文件甚至可以以 GB 为单位。此 SQL 文件将包含您的所有表格以及这些表格中的所有数据。我建议您打开并查看该文件。 然后您应该使用这个新创建的文件并将所有数据导入新数据库。它会将所有这些表和数据放入这个新数据库中。
这是如何做到这一点。首先创建 SQL 文件:
mysqldump -h [SeverIpAddress] -u [UserName] -p[password] YourDbname > db_backup.sql
在远程服务器的情况下使用 -h [SeverIpAddress]。万一它在您自己的系统中重新启动,您不需要使用它。
然后您应该创建新的数据库,比方说 DB_new。创建后,使用 use 命令切换到它。
use DB_new
完成后,现在导入我们在使用 source 命令之前创建的 .SQl 文件。
source YourSQLFilePath
在你的情况下,source db_backup.sql
好的。如果有人遇到同样的问题,这里是解决方案。
首先,承认您有一个名为 'myDatabase' 的数据库,其中有一个名为 'myTable' 的 table 您想要 "upgrade",即您想要修改 table 按 adding/removing 列结构,但将数据保留在内部。
第一步是删除外键(如果有的话)并重命名 "myTable" :
USE `myDatabase`;
ALTER TABLE `myTable` DROP FOREIGN KEY `my_fk_constraint`;
ALTER TABLE `myTable` RENAME TO `old_myTable`;
第二步是导入新的 table 结构,例如使用 SOURCE。
SOURCE C:/new_table_structure.sql
第三步是可选的,但如果您的 table 有很多列,则可能需要此步骤:
USE `myDatabase`;
SET GLOBAL group_concat_max_len = 4294967295;
第四步是存储以下例程:
delimiter //
DROP PROCEDURE IF EXISTS updateConf//
CREATE PROCEDURE updateConf(IN dbName TEXT, IN old_table TEXT, IN new_table TEXT, IN primary_key_name TEXT)
BEGIN
-- get column count in old table
SELECT count(*)
INTO @colNb
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = dbName
AND TABLE_NAME = old_table;
-- get string with all column names from old_table
SELECT GROUP_CONCAT(COLUMN_NAME)
INTO @colNames1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = dbName
AND TABLE_NAME = old_table;
SET @colNames1 = CONCAT(@colNames1, ',');
-- get string with all column names from new_table
SELECT GROUP_CONCAT(COLUMN_NAME)
INTO @colNames2
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = dbName
AND TABLE_NAME = new_table;
-- variables initialization
SET @cpt = 1; -- column number counter
SET @pos = 1; -- position of column name first char
SET @vir = 1; -- next comma position
-- start of loop
label: LOOP
IF @cpt <= @colNb THEN
SET @vir = LOCATE(',',@colNames1,@pos); -- localize next comma
SET @colName = SUBSTRING(@colNames1, @pos, @vir - @pos); -- get column name
SET @pos = @vir + 1; -- update next column position
-- if column is in both tables
IF FIND_IN_SET(@colName, @colNames2) AND @colName != primary_key_name THEN
SET @execut = CONCAT("INSERT INTO ", new_table, " (", primary_key_name, ",", @colName, ") SELECT ", primary_key_name, ",", @colName, " FROM ", old_table, " ON DUPLICATE KEY UPDATE ", new_table, ".", @colName, " = ", old_table, ".", @colName);
PREPARE stmt FROM @execut;
EXECUTE stmt;
END IF;
SET @cpt = @cpt + 1; -- counter increment
-- when all columns parsed
ELSE
LEAVE label; -- end of loop
END IF;
END LOOP label;
END //
delimiter ;
最后一步是在 table 上调用过程,并删除临时 table:
CALL updateConf( 'myDatabase', 'old_myTable', 'myTable', 'primaryKeyName' );
DROP TABLE `old_myTable`;
瞧!只是不要忘记放回您删除的外键:)
当然可以用更好的方法来完成,但我让它正常工作。
谢谢大家!