python实现简易数据库(二) 单表查询和top N实现

上一篇中,介绍了我们的存储和索引建立过程,这篇将介绍SQL查询、单表查询和TOPN实现。

一、SQL解析

正规的sql解析是用语法分析器,但是我找了好久,只知道可以用YACC、BISON等,sqlite使用的lemon,捣整了一天没实现,就用了python的正则表达式。

1、删除无用的空格、跳格符、换行符等;

我们以分号‘;’作为一个sql语句的结束符,在输入分号之前,我们将输入的sql语句串接成一个string,在将整个sql语句的一些无用的字符删掉,

1  def rmNoUseChar(sql): 2     while sql.find("'") != -1:#将引号删除,不论什么类型都当字符类型处理 3         sql = sql.replace("'","") 4     while sql.find('"') != -1: 5         sql = sql.replace('"','') 6     while sql.find('\t') != -1:#删除制表符 7         sql = sql.replace("\t"," ") 8     while sql.find('\n') != -1:#删除换行符 9         sql = sql.replace("\n"," ")10     statements = sql.split(" ")#分割成列表,删除多余空格后在拼接成字符串11     while "" in statements:12         statements.remove("")13     sql=""14     for stmt in statements:15         sql += stmt+ " "16     return sql[0:-1]#最后一个空格删掉

2、关键词大写;

在sql语句中扫描关键字,将关键字大写。这里我们使用了一个技巧,在每个select语句前面多加一个空格,每个关键字前后都加一个空格,这样可以替换单词的部分,如果不加空格,像charity 就会被替换为CHARrity,这不是我们想要的。

oneKeywords = [" SELECT "," FROM "," WHERE ",
    " DESC "," ASC ",
    " DATE "," DAY "," INT "," CHAR "," VARCHAR "," DECIMAL ",
    " SUM "," AVG ","MAX","MIN"," COUNT "," AS "," TOP "," AND "," OR "]
twoKeywords = [" GROUP BY "," ORDER BY "]

3、解析和格式化SELECT子语句;

一个常见的select语句一般包含select、from、where、group by、order by五部分(不考虑嵌套查询),where、group by、order by可以不出现,但如果出现的,在sql语句中必定满足select、from、where、group by、order by的顺序,因此我们定义:

stmtTag = ["SELECT","FROM","WHERE","GROUP BY","ORDER BY",";"]#select 子语句标志词

找到各个子语句的标志词,根据标志词来解析子语句,这里我们定义了一个方法,用来找下一个标志词:

def nextStmtTag(sql,currentTag):#根据当前标志词找下一个标志词
    index = sql.find(currentTag,0)
    for tag in stmtTag:
        if sql.find(tag,index+len(currentTag)) != -1:
            return tag

比如我们测试发现sql语句中有WHERE标志词,那么它一定有where子句,我们通过nextStmtTag()方法得到下一个关键词,如果sql中有GROUP BY, 则下一个标志词就是GROUP BY,如果没有GROUP BY而有ORDER BY,那下一个标志词就是ORDER BY,否则下一个标志词就是分号";",因为一个sql中一定有结束符分号。

4、结合元数据表检查语法错误;

解析完sql的子语句后,我们就可以进行简单的语法检查,结合元数据检查WHERE子句的表是否在数据库中存在,以及其他子语句中的属性是否在WHERE子句的表中,检查的过程中,顺便将属性大写,并将的表名添上,属性的格式统一为:[表名].[属性名],同时对多表查询的where条件做优化,即将单表查询条件放在列表的前面,多表连接放在后面。具体请看下面的例子:

我们输入如下sql语句:

select l_orderkey,o_orderdate,o_shippriority,
min(l_orderkey) as min_odkey,
max(o_shippriority) as max_priority
from customer,orders,lineitem
where
c_mktsegment = "MACHINERY"
and c_custkey = o_custkey
and l_orderkey = o_orderkey
and o_orderdate < "1995-05-20"
and l_shipdate > "1995-05-18"
group by l_orderkey,o_orderdate,o_shippriority
order by o_orderdate desc,o_orderdate;

 解析的结果(已通过语法检查): 

{'FROM': ['CUSTOMER', 'ORDERS', 'LINEITEM'],
 'GROUP': ['LINEITEM.L_ORDERKEY',
           'ORDERS.O_ORDERDATE',
           'ORDERS.O_SHIPPRIORITY'],
 'ORDER': [['ORDERS.O_ORDERDATE', 'DESC'], ['ORDERS.O_ORDERDATE', 'ASC']],
 'SELECT': [['LINEITEM.L_ORDERKEY', None, None],
            ['ORDERS.O_ORDERDATE', None, None],
            ['ORDERS.O_SHIPPRIORITY', None, None],
            ['LINEITEM.L_ORDERKEY', 'MIN', 'min_odkey'],
            ['ORDERS.O_SHIPPRIORITY', 'MAX', 'max_priority']],
 'WHERE': [['CUSTOMER.C_MKTSEGMENT', '=', 'MACHINERY'],
           ['ORDERS.O_ORDERDATE', '<', '1995-05-20'],
           ['LINEITEM.L_SHIPDATE', '>', '1995-05-18'],
           ['CUSTOMER.C_CUSTKEY', '=', 'ORDERS.O_CUSTKEY'],
           ['LINEITEM.L_ORDERKEY', '=', 'ORDERS.O_ORDERKEY']]}

可以看到我们将整个sql解析成一个字典,字典的键是子语句标志词,值是格式化的子语句,这个解析结果跟JSON格式差不多。对于group by和from子语句只是简单的表名和属性名,因此就使用一个list表示,而其他子语句比较复杂,我们对其子语句的每个部分用list表示,如order子语句,不光有属性还有升序或降序描述;而select还有聚集函数和重命名;where子句我们只考虑大于、等于和小于的条件,即每个where条件可以用过一个三元组表示。不出现的部分我们用None补齐。

这就是我们的解析select sql的大体过程,细节不再介绍,因为这个解析方法实在不高明,上不了台面,正规军都是用的句法和语法解析器,我们打游击战的。

查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/extra/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索sql
, select
, 语句
, python文件语句解析
, 空格
, sql语句实现
, sql语句解析
, 子语句查询类型错误
, 一个
, 子查询语句格式
子句
python 实现数据库、简易数据库、简易数据库软件、sql 简易数据库、简易数据库编程软件,以便于您获取更多的相关知识。

时间: 2024-11-29 13:47:55

python实现简易数据库(二) 单表查询和top N实现的相关文章

python实现简易数据库(三) join多表连接和group by分组

上一篇里面我们实现了单表查询和top N查询,这一篇我们来讲述如何实现多表连接和group by分组. 一.多表连接 多表连接的时间是数据库一个非常耗时的操作,因为连接的时间复杂度是M*N(M,N是要连接的表的记录数),如果不对进行优化,连接的产生的临时表可能非常大,需要写入磁盘,分多趟进行处理. 1.双表等值join 我们看这样一个连接sql: select PS_AVAILQTY,PS_SUPPLYCOST,S_NAME from SUPPLIER,PARTSUPP where PS_SUP

求一条sql语句,单表查询的

问题描述 求一条sql语句,单表查询的 表结构 (姓名,课程,成绩) 现在求获的该表总成绩最高学员的名字 解决方案 mysql 数据库select sum(成绩) as t from table group by 姓名 order by t limit 0,1 oracle数据库 select * from (select sum(成绩) as t from table group by 姓名 order by t) WHERE ROWNUM<=1 sqlserver数据库 select top

在Derby数据库中联表查询的时候遇到两个表中相同的列名如何使用rs.getString(表名.列名查询)?表名.列名试过不行

问题描述 在Derby数据库中联表查询的时候遇到两个表中相同的列名如何使用rs.getString(表名.列名查询)?表名.列名试过不行.希望高手回答!!!!! 解决方案 解决方案二:自己顶顶先等待高手的答复~~~~~解决方案三:好像一般数据库的都不行一种方式用列序号取,最好还是改成其他名字解决方案四:终于有兄弟回复了,感激一下先.但是很多数据库都是支持的,比如说我们可爱的MySQL,SQLServer之类的稳定的数据库.Derby肯定是有的,但是我们不知道罢了.它的语法格式解决方案五:查询的时

用SQL进行单表查询

  单表查询是相对多表查询而言的,指从一个数据表中查询数据.4.2.1 查询所有的记录    在[命令编辑区]执行输入"select * from scott.emp",然后单击[执行]按钮,出现如图4.3所示的emp数据表所有记录.    [参见光盘文件]:\第4章\4.2\421.sql.    select * from 数据表,这里的"*"代表数据表中所有的字段.4.2.2 查询所有记录的某些字段    在[命令编辑区]输入"select empn

6.单表查询

1.语法格式         select语句的功能就是查询数据,在SQL语句中功能最丰富,可单表查询.多表连接查询.子查询. SELECT  NAME, grade FROM student WHERE grade >80; 数据源student可以是表.视图等:select后列表用于确定选择哪些列(* 即所有列),where确定选择哪些行(无则选出所有行). select语句中可使用算术运算符(+.-.*./)形成算术表达式,用于数值型.日期型的数据列.变量.常量:运算符可在两列间进行运算.

oracle 全表单表查询慢,如何解决

问题描述 各位高手如题,表结构如图!~ 问题补充:那请问如果有大文本的内容的时候不用clob,那如何办?!tnt-scott 写道 解决方案 1.检索lob字段的时候,按需去取lob字段,如果你不用,则给它设成null,比如我要id='10'的lob字段,那么sql:select decode(id,'10',lob_col,null) from tb2.给lob字段建立单独的表空间,并设定把CACHE 设定成reads提高读取速度.代码:--创建表空间CREATE TABLESPACE MON

python实现简易数据库(一) 存储和索引建立

最近没事做了一个数据库project,要求实现一个简单的数据库,能满足几个特定的查询,这里主要介绍一下我们的实现过程,代码放在过ithub,可参看这里.都说python的运行速度很慢,但因为时间比较急,工作量大,我们还是选择了高效实现的python. 一.基本要求 1.设计存储方式 测试的数据量大小为1.5GB,最大的表有6,001,215条记录.最大限度减少I/O次数,减少磁盘占有空间. 2.实现和优化group by,order by 对大表进行group by 聚集.排序,提高查询效率 3

求jsp+javaBean连数据库实现单表增删改查功能的源程序代码

问题描述 代码简洁有注释更好,学习用.我的邮件是noryaland@gmail.com 解决方案 解决方案二:不能沉解决方案三:我们学校有这个我去给你找找一年多了不知道放哪里去了呵呵解决方案四:看来是没什么用被我删了不好意思解决方案五:求一份代码,用以研习.解决方案六:同求呵呵解决方案七:www.pudn.com解决方案八:数据库最好是oracle或sqlserver,因为我只懂这两种解决方案九:代码到,给分解决方案十:随便到网上找一下就有了解决方案十一:http://hi.baidu.com/

【sql查询与优化】1.单表查询

注:以下所有sql案例均取自"oracle查询优化改写技巧与案例"丛书. EMP表的详细: 1.查询表中所有的行与列 查询所有信息, SQL> select * from emp;      EMPNO ENAME                JOB                       MGR HIREDATE       SAL        COMM       DEPTNO ---------- -------------------- -------------