【问题标题】:Python - convert multiple insert statements into onePython - 将多个插入语句转换为一个
【发布时间】:2021-04-26 06:17:49
【问题描述】:

我现在有以下问题:

我有一个只有 2 列的数据库表:ID (primary key, auto increment) 和值 (varchar(100))。

现在我有一个sql 文件来用值填充该表。重点是:首先,文本文件只有单个插入,因此插入的每个值都是单个值。一般不会有问题,如果不是大约 1000 万行...

为了更有趣,我有 5 个这样的表和 5 个带有插入语句的 .sql 文件。

现在我尝试按原样运行 sql 文件,即使只有 100k 行,也需要一个小时......所以插入 1000 万个条目大约需要 100 个小时......所有表的 x5 大约需要500 小时,大约是 21 天。我不想在这里看到任何事情......

现在根据我的阅读,如果一个插入语句包含多个要插入的值...例如:

insert into knownPasswords3 (password)
values ('! -');

insert into knownPasswords3 (password)
values ('! 3');

insert into knownPasswords3 (password)
values ('! 5');

insert into knownPasswords3 (password)
values ('! ?');

insert into knownPasswords3 (password)
values ('! C');

insert into knownPasswords3 (password)
values ('! c');

会变成:

insert into knownPasswords3 (password)
values ('! -','! 3','! 5','! ?','! C''! c');

作为一个例子...根据我的阅读,每个插入语句大约 40 个值将是一个相当不错的值...

这就是我想要得到的。从一个包含 400 个单个语句(作为示例)的 sql 文件到一个包含 10 个语句,每个语句有 40 个值的 sql 文件。

现在我已经尝试了很多正则表达式和 Notepad++ 中的不同方法作为示例,但我无法真正让它工作......

然后,如果 python 可能能够以一种优雅的方式执行此操作(直接将其插入数据库或仅转换文本文件)。我认为插入不会有太大帮助,所以现在我正在寻找一种将文件转换为另一个文件的方法,只是它具有提到的单个语句的减少..

我的伪代码类似于:

open file.sql
i = 0;
for each line in file.sql:
   if i==40:
      i=0
      break
   else:
      remove text "insert into knownPasswords3 (password) values ("
      remove text ");"
      add text ,

但是,我已经尝试过了,但无法让这些部件正常工作......

任何人都可以让我走上正确的道路吗?是否有一个库或某事使这更容易?

【问题讨论】:

    标签: python mysql sql sql-insert bulkinsert


    【解决方案1】:

    我认为问题出在您尝试准备的插入语句中。它应该如下所示:

    insert into knownPasswords3 (password)
    values ('! -'),('! 3'),('! 5'),('! ?'),('! C'),('! c');
    

    现在您插入 6 行 1 列,而您的查询插入 1 行 6 列。

    【讨论】:

    • 是的,好吧,我在这里输入的内容可能有问题。但是,问题是,如何将我的多个单个插入语句放入一些更大的语句中(每个语句有 40 个)?跨度>
    • 手动或使用自定义代码,将insert into knownPasswords3 (password) values 替换为,,第一个除外,您的查询已准备就绪
    • 是的,这正是我在我的问题中写的......我只是不知道如何真正让它在 python 中工作......特别要记住,每个插入语句应该有大约插入 40 个值,而不是一次插入 1000 万个
    【解决方案2】:

    此代码纯粹基于文件处理、列表切片和字符串操作。它读取一个名为“file.sql”的文件,并在另一个名为“file2.sql”的文件中保存插入语句,每个语句有 40 个值。

    希望这能回答你的问题。

    # reading the lines from SQL file
    file1 = open('file.sql', 'r')
    lines = file1.readlines()
    file1.close()
    
    # removing the first line
    lines.pop(0)
    
    # getting a list of all the values
    list_of_values = []
    for i in range(0, len(lines), 3):
      list_of_values.append(lines[i].split("'")[1])  
    
    # setting the limits to 40 elements per insert statement
    lowerlimit = -40
    upperlimit = 0
    
    # flag to check whether the number of values left is greater than 40
    remaining_values = True
    
    # second file to save output
    file2 = open('file2.sql', 'w')
    
    while remaining_values:
    
      # setting flag if remaining values less than 40
      if len(list_of_values)-upperlimit <= 40:
        remaining_values = False
    
      # updating limits as we move traverse the list
      lowerlimit = upperlimit
      upperlimit = min(upperlimit + 40, len(list_of_values)) 
    
      # formulating insert statement
      output = 'insert into knownPasswords3 (password)\nvalues '
    
      # adding 40 values to each insert statement
      if remaining_values == True:
        output += str(list_of_values[lowerlimit:upperlimit]).replace('[','(').replace(']',')') + ";\n\n"
      else:
        output += str(list_of_values[lowerlimit:upperlimit]).replace('[','(').replace(']',')') + ";"
    
      # writing insert statement to output file
      n = file2.write(output)    
    
    # closing the file
    file2.close()
    

    对一个示例文件进行测试,它会给出以下输出:

    insert into knownPasswords3 (password)
    values ('! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?');
    
    
    insert into knownPasswords3 (password)
    values ('! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3');
    
    
    insert into knownPasswords3 (password)
    values ('! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c');
    
    
    insert into knownPasswords3 (password)
    values ('! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c', '! -', '! 3', '! 5', '! ?', '! C', '! c');
    

    【讨论】:

    • 感谢您的回答。总的来说,这似乎没问题,但是,我当时似乎有编解码器问题...获取UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 6381: character maps to &lt;undefined&gt;....尝试使用econdig='utf-8'打开但也抛出错误...尝试使用@987654326 @ 作为二进制模式,但是在将其附加到列表时会出现问题.. 有什么想法吗?
    • 你在那里把encoding 拼错为econdig
    • 另外,您的文件中有哪些字符?如果我掌握了文件,甚至是导致错误的子集,我可能会提供帮助。
    • @yeah,这实际上只是 stackoverflow 上的一个错字。另外,我现在在这里上传了一个文件:wetransfer.com/downloads/… 这也是它现在失败的文件......你可以试试吧
    • @nameless 那是因为文件中有一些非 ascii 字符,您应该在将文件传递给 open 函数之前正确格式化文件。行尾字符似乎有错误
    【解决方案3】:

    试试这个:

    infile = open('file.sql', 'r' )
    
    ins_stmnts = {}
    for line in infile:
        if 'insert' in line:
          ins_stmnt, vals = line.split('values')
          if ins_stmnt in ins_stmnts.keys():
            ins_stmnts[ins_stmnt].append(vals)
          else:
            ins_stmnts[ins_stmnt] = [vals]
    
    infile.close()
    
    outfile = open("converted.sql", 'w')
    
    for ins_stmnt, vals in ins_stmnts.items():
      val_str = "("
      for i, val in enumerate(vals):
        if i%39==0:
          val = val.rstrip(');\n')
          val = val.lstrip(' (')
          val_str += val
          outfile.write(ins_stmnt + "values " + val_str + ');\n')
          val_str = "("
          break
        else:
          val = val.rstrip(');\n')
          val = val.lstrip(' (')
          val_str += val + ','
    
      if len(val_str)>1:
        outfile.write(ins_stmnt + "values " + val_str.rstrip(',') + ');\n')
    
    outfile.close()
    

    【讨论】:

      【解决方案4】:

      您可以查看transactions。它们将必须一起执行或不执行的语句组合在一起(有点像将多个语句视为一个语句)。不完全确定它是否是您正在寻找的。​​p>

      【讨论】:

        猜你喜欢
        • 2022-07-23
        • 2015-04-03
        • 1970-01-01
        • 2012-03-19
        • 1970-01-01
        • 2023-03-09
        • 2022-01-26
        • 2022-01-19
        • 2015-05-08
        相关资源
        最近更新 更多