【问题标题】:How to parse MySQL built-code from within Python?如何从 Python 中解析 MySQL 内置代码?
【发布时间】:2023-03-27 00:31:01
【问题描述】:

I've exported my MySQL database to a .txt/.sql file (link) 并想用它在其他计算机上重建数据库。虽然在 HeidiSQL 中运行脚本工作得非常好,但我想在启动我的应用程序之前确保所有表都存在并且正确。

我可以将构建的代码复制粘贴到我的 Python 代码中,但导出是我的数据库的直接表示,不应该包含任何错误,而复制粘贴...所以我尝试解析文件,但我的解析技巧还有很多不足之处。

这是代码的sn-p:

CREATE TABLE IF NOT EXISTS `data` (
  `dataid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `measurementid` int(10) unsigned NOT NULL DEFAULT '0',
  `frame` int(10) unsigned NOT NULL,
  `sensor_row` int(10) unsigned NOT NULL,
  `sensor_col` int(10) unsigned NOT NULL,
  `value` float unsigned NOT NULL,
  PRIMARY KEY (`dataid`),
  UNIQUE KEY `measurementid_frame_sensor_row_sensor_col` (`measurementid`,`frame`,`sensor_row`,`sensor_col`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

所以假设数据库data 已经创建,我正在寻找一种方法来解析构建的代码并创建所有必需的表(如果它们不存在或更改) 如果他们改变了。

关于如何解决这个问题的任何建议?

【问题讨论】:

  • 将 SQL 导出语句粘贴到 phpmyadmin。 (除非这是您尝试编写脚本并重复多次的工作)。
  • @Ian,我仍在大量更改和调整我的应用程序和数据库,但由于不是每个测试我的应用程序的人都具备足够的技术能力,我想确保它正确完成。
  • 在这种情况下,您必须自己应用更改。在工作时将所做的更改记录在文本文件中,并在应用代码版本时应用它们。我强烈建议使用诸如 GIT 之类的 VCS 来保持版本正常。

标签: python mysql


【解决方案1】:

您可以直接通过 python 数据库适配器从文件中完全执行 sql:

import MySQLdb
sql_dump = open('builtcode.sql', 'r').read()

conn = MySQLdb.connect(db='soans', passwd='*****')
cur = conn.cursor()

cur.execute(sql_dump)

cur.connection.close()

给予:

mysql> show tables;
+-----------------+
| Tables_in_soans |
+-----------------+
| anamnesis_main  |
| averagecontact  |

【讨论】:

  • 我相信他想阅读 sql 脚本并根据它们是否存在有条件地创建/更改表。
【解决方案2】:

只需读取文件并执行 sql 字符串

我对您还需要做什么感到困惑。如果表已经存在,则创建表语句将不会运行。任何 alter 语句都会运行。

如果您需要将当前架构与您尝试将其更新到的架构进行比较,这比“解析”文件所暗示的更难,您可能希望使用某种迁移框架(南for django 是我的最爱之一)或模式比较工具。

【讨论】:

  • 想详细说明如何读取文件?因为我不知道如何将文件拆分为单独的 sql 字符串。您是否有更多关于如何比较模式的信息,因为我没有这方面的经验。
  • Sql 语句是用分号分隔的,不是吗?你不应该有任何理由必须单独运行它们,你可以打开文件,读取它,然后运行字符串。至于比较模式,这是一个比stackoverflow答案能够涵盖的复杂得多的问题。整个行业的软件公司都在制造具有模式和/或数据比较工具的 sql 工具。
  • 啊,我不知道这么简单。我尝试了读取+执行,它运行良好。至于模式部分,如果它们不一样,我只需要删除表(不必保留数据)并重建它们。 Any alter statements would run. 会不会和我构建的代码一样,只有在不同的时候才会改变?
  • 如果您不需要数据,我只会删除数据库并每次从头开始创建它。我曾在拥有庞大升级脚本的商店工作,该脚本使用从模式表中选择的 if 语句来查看它们是否应该添加一列,实际上,这是一团糟。由于您使用的是 python,因此您可以使用 ORM(如 django 的 ORM)和迁移库(如 south,在此处阅读更多内容:south.aeracode.org/docs/about.html)来使您的数据库保持最新。
  • 我认为这个选项实际上是最安全的,因为尝试迁移所有数据(在这个阶段)将花费我比重新处理更多的工作。
【解决方案3】:

您可以尝试sqlparse module 将文件拆分为单独的语句,然后执行每个语句。

您还可以通过高级方式操作 SQL 令牌,例如 stripping out all comments (except those inside functions)。您可以使用此技术从 CREATE TABLE 语句中解析表名并检查表是否存在。

以下是拆分语句的示例:

import sqlparse

queries = '''
CREATE TABLE foo (id INTEGER);
CREATE TABLE bar (id INTEGER, name VARCHAR);
SELECT foo FROM bar WHERE id IN (1,2,3);
DELETE FROM bar WHERE id IN (3, 4);
-- a comment
DELETE FROM bar WHERE name IN ('chaos','atlas');
'''

for i, stmt, in enumerate(sqlparse.split(queries)):
    sql = stmt.strip()
    if not sql:
        continue
    print i, sql

输出:

0 CREATE TABLE foo (id INTEGER);
1 CREATE TABLE bar (id INTEGER, name VARCHAR);
2 SELECT foo FROM bar WHERE id IN (1,2,3);
3 DELETE FROM bar WHERE id IN (3, 4);
4 -- a comment
DELETE FROM bar WHERE name IN ('chaos','atlas');

【讨论】:

  • 如果我在我构建的代码上尝试您的代码示例,它会返回一个大块,而不是单独的语句。知道如何调整它,使其只返回单独的 sql 语句吗?
猜你喜欢
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 2019-09-22
  • 1970-01-01
  • 2021-11-22
  • 2016-09-10
  • 1970-01-01
  • 2011-06-20
相关资源
最近更新 更多