财务数据分析sql python_数据开发_Python解析sql提取表

基于Python实现解析SQL代码中的表

1.问题:

有一批SQL代码,需要提取其中用到的表。

2.实现思路:

01.通过正则匹配的方式,将sql分为三类 create from|join insert的这几种情况

02. 使用脚本语言Python开发,快捷

3.注意事项

01.前提假设:

SQL都是规范的可运行的。 schema.table_name 的形式或者 table_name的形式,

如果schema 和 table_name之间有多个空格的情况,这种要特殊处理一下

test_a. my_table_nm 这种情况会把只提取出 test_a. 的形式,针对这种情况,可以采用以下方式

处理例如: line = sub(r"test_a. ", r'test_a.', line)

02. 注释的代码不需要

代码实现

代码中内容,只是日常处理数据使用,没有考虑正式生产环境,比如没有日志记录等部件。如果要到生产环境,要做的工作还不少。

在日常中使用,如果要用多次的话,还是写成工具的形式

#!/usr/bin/env python

# -*-coding:utf-8-*-

# @file extract_sql_table.py

from re import match, sub, compile

import os

import pandas as pd

def extract_pure_field(sql_file_name, res_file):

"""去除多余空格,空行, 注释 配置 等"""

# 后缀换成 txt

with open(sql_file_name, mode='r', encoding='utf8') as fileObj, \

open(res_file, mode='w', encoding='utf8') as f2:

for line, data in enumerate(fileObj):

# .strip() 去除字符串首尾的空格

line_text = data.strip().lower()

# 有 insert 的行<默认insert 紧跟着表且在同一行>

if match('^--.*|^set .*', line_text) is None:

# 多个空格变为一个空格

line_text_after = sub(' +', ' ', line_text)

print("行数 ", line, sep=',')

f2.writelines(line_text_after+"\r\n" + " ")

def extract_table_name(sql_file_name, extract_flag='3'):

"""提取from 或者 join后面的 Table

extract_flag='1' overwrite|into 后的表名

extract_flag='2' create 后的表名

extract_flag='3' from|join 的表名

"""

with open(sql_file_name, mode='r', encoding='utf-8') as fileObj:

job_file = os.path.split(os.path.splitext(sql_file_name)[0])[1]

# read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中

lines = fileObj.read()

# 删除空行

line_text_after = sub(r"\n[\s| ]*\n", '', lines)

# windows的换行是\r\n,unix的是\n,mac的是\r-变成一行的字符串

# python本身对string长度无强制性限制。使用过程中主要需要考虑电脑性能和程序效率

# 将文档变为一行,解决换行引起的问题,这里还可以通过正则的方式,在这里就暂时没考虑这种实现

line = sub(' +', ' ', line_text_after.replace('\n', '').replace('\r', '')).lower()

# 部分表名不规范 text. Test_D_history 多出了个空格,这种情况处理需额外添加条件处理

# 数字、26个英文字母或者下划线 和 英文句号组成的字符串,这部分的正则表达式可以再了解了解

if extract_flag == '1':

pattern_tuple = compile('insert (?:overwrite table|into table|overwrite|into) [0-9a-zA-Z_\\.]{1,}')

pattern_string = "overwrite|into"

table_location = -1

elif extract_flag == '2':

pattern_tuple = compile('create (?:table if not exists|table) [0-9a-zA-Z_\\.]{1,}')

pattern_string = "create"

table_location = -1

else:

pattern_tuple = compile('(?:from|join) [0-9a-zA-Z_\\.]{1,}.*?')

pattern_string = 'from|join'

table_location = 1

# 表名提取

# 存储结果

table_list = []

data_tuple = pattern_tuple.findall(line)

for table in data_tuple:

table_name = table.split(" ")[table_location]

comb_job_table_data = job_file, pattern_string, table_name

print(comb_job_table_data)

table_list.append(comb_job_table_data)

return table_list

if __name__ == '__main__':

infile_name = r"C:/Users/Desktop/test.sql"

out_put_file = r"C:/Users/Desktop/select_table_nm.txt"

res_file = os.path.splitext(infile_name)[0] + '.txt'

# 处理文件注释等情况

extract_pure_field(infile_name, res_file)

# 提取表 1 是 overwrite|into表, 2是create 其余情况是 from|join

table_job_list = extract_table_name(res_file, "3")

# 将表写到数据框

result_data = pd.DataFrame(table_job_list).drop_duplicates()

# 追加的形式写入

result_data.to_csv(path_or_buf=out_put_file, mode='a', index=False, header=False)

# 移除中间文件

#os.remove(res_file)

以上代码,简单的实现了目前的需求,后续将这部分做成工具,可以方便后续的使用。结合其他文件处理工具,可以更好的处理各种情况

参考

参考了部分正则表达式的语法等数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值