从.sql文件中“删除”一段行的问题

0 投票
2 回答
524 浏览
提问于 2025-04-18 12:49

我正在写一个脚本,目的是从一个SQL转储文件中删除一段行(简单来说,就是清理掉我们不想恢复的表)。我以为我已经搞定了,但在尝试把处理后的文件恢复到我的数据库时,我发现脚本在写回文件时,缺少了比预期更多的行,导致恢复失败。这是我这方面的一个小尝试:

#!/usr/bin/python

to_keep = []
to_remove = []

f = open("backuptest.sql","r")
lines = f.readlines()

f.close()

### Function to remove lines associated with a table block
def remove_lines(table_name):
    for i in range(0, len(lines)):
        line = lines[i]
        if "structure" in line and table_name in line:
            for j in range(i, len(lines)):
                to_remove.append(lines[j])
                if "UNLOCK TABLES;" in lines[j]:
                    break
        if line not in to_remove:
            to_keep.append(line)
            f.write(line)

print "Finding lines"

f = open("backuptest.sql", "w")
remove_lines("advanced_searches")
f.close()

f = open("backuptest.sql", "w")
remove_lines("test_table2")
f.close()

f = open("backuptest.sql", "w")
remove_lines("test_table3")
f.close()

这是SQL文件中一个块的样子,供参考:

-- Table structure for table `advanced_searches`
--

DROP TABLE IF EXISTS `advanced_searches`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `advanced_searches` (
  `batch_size` int(11) NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `advanced_searches`
--

LOCK TABLES `advanced_searches` WRITE;
/*!40000 ALTER TABLE `advanced_searches` DISABLE KEYS */;
/*!40000 ALTER TABLE `advanced_searches` ENABLE KEYS */;
UNLOCK TABLES;

我开始这个脚本时,是通过匹配这个块中的第一行(包含“structure”和表名的字样),然后我试图从那一行开始,一直到“UNLOCK TABLES;”这一行。但实际上发生的情况是,它删除了脚本中所有的“UNLOCK TABLES;”实例,包括那些我不想删除的块中的内容,而且还删除了每个块中接下来的这一行“) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;”(也就是这一行的右括号及其后面的内容)。

谢谢任何帮助。我会继续努力找出我遗漏的部分。

2 个回答

0

最好不要用全局变量来代替函数的参数,因为使用参数可以让函数和它所在环境之间的关系更加清晰。既然你想从一个文件中删除几个表格,最好的方法是先把所有的行读进来,然后把需要的行作为新的结果返回。

def remove_lines(lines, table_name):
   output_lines = []
   for line in lines:
       if line.startswith("-- structure for table") and table_name in line:
           while "UNLOCK TABLE" not in line:
               line = lines.next()
       else:
           output_lines.append(line)
   return output_lines

这个函数应该接收一组行和一个表名,然后返回一个可以进一步处理的行列表。最后得到的结果可以用来覆盖原来的文件(你确定不想保留备份吗?)像这样:

with open("backuptest.sql","r") as f:
    lines = f.readlines()
for table_name in ("advanced_searches", "test_table2", "test_table1"):
    lines = removelines(lines, table_name)
with open("backuptest.sql", "w") as f
    f.writelines(lines)
1

试试 sqlparse

$ pip install sqlparse

这是教程中的快速测试:

>>> import sqlparse
>>> sql = "select * from foo; select * from bar;"
>>> res = sqlparse.split(sql)
>>> res
[u'select * from foo;', u'select * from bar;']

应用到你的 SQL 脚本上:

>>> sql = """-- Table structure for table `advanced_searches`
... --
... 
... DROP TABLE IF EXISTS `advanced_searches`;
... /*!40101 SET @saved_cs_client     = @@character_set_client */;
... /*!40101 SET character_set_client = utf8 */;
... CREATE TABLE `advanced_searches` (
...   `batch_size` int(11) NOT NULL DEFAULT '0'
... ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
... /*!40101 SET character_set_client = @saved_cs_client */;
... 
... --
... -- Dumping data for table `advanced_searches`
... --
... 
... LOCK TABLES `advanced_searches` WRITE;
... /*!40000 ALTER TABLE `advanced_searches` DISABLE KEYS */;
... /*!40000 ALTER TABLE `advanced_searches` ENABLE KEYS */;
... UNLOCK TABLES;"""
...
>>> res = sqlparse.split(sql)
>>> res
[u'-- Table structure for table `advanced_searches`\n--\n\nDROP TABLE IF EXISTS `advanced_searches`;',
 u'/*!40101 SET @saved_cs_client     = @@character_set_client */;',
 u'/*!40101 SET character_set_client = utf8 */;',
 u"CREATE TABLE `advanced_searches` (\n  `batch_size` int(11) NOT NULL DEFAULT '0'\n) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;",
 u'/*!40101 SET character_set_client = @saved_cs_client */;',
 u'--\n-- Dumping data for table `advanced_searches`\n--\n\nLOCK TABLES `advanced_searches` WRITE;',
 u'/*!40000 ALTER TABLE `advanced_searches` DISABLE KEYS */;',
 u'/*!40000 ALTER TABLE `advanced_searches` ENABLE KEYS */;',
 u'UNLOCK TABLES;']

这样就能得到正确解析的脚本,最后要做的就是逐个筛选,挑选出那些看起来需要的部分。这一步就留给你自己去完成。

撰写回答