sql和myeclipse怎么连接(Dataset基于SQLAlchemy的便利工具)

sql和myeclipse怎么连接(Dataset基于SQLAlchemy的便利工具)(1)

作者: w2n1ck

数据集使得数据库中的数据读取和写入数据就像阅读和编写JSON文件一样简单。

dataset对于操作JSON、CSV文件、NoSQL非常好用。

import dataset

连接MySQL数据库:

db = dataset.connect('mysql://username:password@10.10.10.10/ctf?charset=utf8') 用户名:username,密码:password,数据库地址(地址 端口):10.10.10.10,database名: ctf 连接SQLite数据库: db = dataset.connect('sqlite:///ctf.db') 连接PostgreSQL数据库: db = dataset.connect('postgresql://scott:tiger@localhost:5432/mydatabase')

一定要注意指定字符编码

table = db['city'] #(选择city表) user = table('name') # 找出表中'name'列属性所有数据 res = db.query('select name from table limit 10') # 如果不需要查看全部数据的话最好用limit,因为全部数据的载入非常非常耗时间 for x in res: print x['name'] # 选name字段的数据 table.insert(dict(name='John Doe', age=37)) table.insert(dict(name='Jane Doe', age=34, gender='female')) john = table.find_one(name='John Doe')

在数据库中查找是否有同时满足多个条件的数据:table.find_one(属性1=属性值1, 属性2=属性值2, …)

注:find_one速度很慢

插入数据

dataset会根据输入自动创建表和字段名

table = db['user'] # 或者table = db.get_table('user') table.insert(dict(name='John Doe', age=46, country='China')) table.insert(dict(name='Jane Doe', age=37, country='France', gender='female')) # 主键id自动生成

更新数据

table.update(dict(name='John Doe', age=47), ['name']) # 第二个参数相当于sql update语句中的where,用来过滤出需要更新的记录

事务操作

事务操作可以简单的使用上下文管理器来实现,出现异常,将会回滚

with dataset.connect() as tx: tx['user'].insert(dict(name='John Doe', age=46, country='China')) # 相当于: db = dataset.connect() db.begin() try: db['user'].insert(dict(name='John Doe', age=46, country='China')) db.commit() except: db.rollback() # 也可以嵌套使用: db = dataset.connect() with db as tx1: tx1['user'].insert(dict(name='John Doe', age=46, country='China')) with db as tx2: tx2['user'].insert(dict(name='Jane Doe', age=37, country='France', gender='female'))

从表获取数据

  • 对于left join,不管on后面跟什么条件,左表的数据全部查出来,因此要想过滤需把条件放到where后面

  • 对于inner join,满足on后面的条件表的数据才能查出,可以起到过滤作用。也可以把条件放到where后面

  • 在使用left jion时,on和where条件的区别如下:

    1. on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。

    2. where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。

    order by的用法

    使用order by,一般是用来,依照查询结果的某一列(或多列)属性,进行排序(升序:ASC;降序:DESC;默认为升序)。 当排序列含空值时: ASC:排序列为空值的元组最后显示。 DESC:排序列为空值的元组最先显示。 可以把null值看做无穷大 select * from s order by sno desc, sage asc

    group by的用法

    group by按照查询结果集中的某一列(或多列),进行分组,值相等的为一组 1、细化集函数(count,sum,avg,max,min)的作用对象: 未对查询结果分组,集函数将作用于整个查询结果。 对查询结果分组后,集函数将分别作用于每个组。 SELECT cno,count(sno) from sc group by cno 2、GROUP BY子句的作用对象是查询的中间结果表 分组方法:按指定的一列或多列值分组,值相等的为一组。 使用GROUP BY子句后,SELECT子句的列名列表中只能出现分组属性(比如:sno)和集函数(比如:count()) select sno,count(cno) from sc group by sno 3、多个列属性进行分组 select cno,grade,count(cno) from sc group by cno,grade 4、使用HAVING短语筛选最终输出结果 只有满足HAVING短语指定条件的组才输出。 HAVING短语与WHERE子句的区别:作用对象不同。 1、WHERE子句作用于基表或视图,从中选择满足条件的元组。 2、HAVING短语作用于组,从中选择满足条件的组 select sno from sc group by sno having count(cno)>3 select sno,count(cno) from sc where grade>60 group by sno having count(cno)>3

    MySQL的左连接、右连接、等值连接

    1.左连接(left join )

    select m.columnname……,n.* columnname….. from left_table m left join right_table n on m.columnname_join=n.columnname_join and n.columnname=xxx where m.columnname=xxx…..

    ON是连接条件,用于把2表中等值的记录连接在一起,但是不影响记录集的数量。若是表left_table中的某记录,无法在表right_table找到对应的记录,则此记录依然显示在记录集中,只是表right_table需要在查询显示的列的值用NULL替代;

    ON连接条件中表n.columnname=xxx用于控制right_table表是否有符合要求的列值还是用NULL替换的方式显示在查询列中,不影响记录集的数量;

    WHERE字句控制记录是否符合查询要求,不符合则过滤掉

    2.右连接(right join)

    select m.columnname……,n.* columnname….. from left_table m right join right_table n on m. columnname_join=n. columnname_join and m. columnname=xxx where n.columnname=xxx…..

    3.等值连接

    select m.columnname……,n.* columnname….. from left_table m [inner] join right_table n on m. columnname_join=n. columnname_join where m.columnname=xxx….. and n.columnname=xxx…. 或者 select m.columnname……,n.* columnname….. from left_table m , right_table n where m. columnname_join=n. columnname_join and m.columnname=xxx….. and n.columnname=xxx….

    ON是连接条件,不再与左连接或右连接的功效一样,除了作为2表记录匹配的条件外,还会起到过滤记录的作用,若left_table中记录无法在right_table中找到对应的记录,则会被过滤掉;

    WHERE字句,不管是涉及表left_table、表right_table上的限制条件,还是涉及2表连接的条件,都会对记录集起到过滤作用,把不符合要求的记录刷选掉;

    jinja2获取循环索引

    jinja2获取循环{% for i in n %}的索引使用loop.index {% for i in names %} <tr> <td>{{ loop.index }}</td> //当前是第x条 <td>{{ i.name }}</td> </tr> {% endfor %}

    flask 重定向和错误

    可以用redirect()函数把用户重定向到其它地方。放弃请求并返回错误代码,用abort()函数。

    from flask import abort, redirect, url_for @app.route('/') def index(): return redirect(url_for('login')) @app.route('/login') def login(): abort(401) this_is_never_executed()

    默认情况下,错误代码会显示一个黑白的错误页面。如果你要定制错误页面,可以使用errorhandler()

    装饰器:

    from flask import render_template @app.errorhandler(404) def page_not_found(error): return render_template('page_not_found.html'), 404

    注意 render_template()调用之后的 404 。这告诉Flask,该页的错误代码是404 ,即没有找到。默认为200,也就是一切正常。

    flask CSRF防护机制

    @app.before_request def csrf_protect(): if request.method == "POST": token = session.pop('_csrf_token', None) if not token or token != request.form.get('_csrf_token'): abort(403) def some_random_string(): return hashlib.sha256(os.urandom(16).hexdigest()) def generate_csrf_token(): if '_csrf_token' not in session: session['_csrf_token'] = some_random_string() return session['_csrf_token']

    在flask的全局变量里面注冊 上面那个生成随机token的函数

    app.jinja_env.globals[‘csrf_token’] = generate_csrf_token

    在网页的模板是这么引入的

    <form method=post action=""> <input name=_csrf_token type=hidden value="{{ csrf_token() }}">

    flask上下文处理器

    Flask 上下文处理器自动向模板的上下文中插入新变量。上下文处理器在模板渲染之前运行,并且可以在模板上下文中插入新值。上下文处理器是一个返回字典的函数,这个字典的键值最终将传入应用中所有模板的上下文:

    @app.context_processor def inject_user(): return dict(user=g.user)

    上面的上下文处理器使得模板可以使用一个名为user值为g.user的变量。不过这个例子不是很有意思,因为g在模板中本来就是可用的,但它解释了上下文处理器是如何工作的。

    变量不仅限于值,上下文处理器也可以使某个函数在模板中可用(由于Python允许传递函数):

    @app.context_processor def utility_processor(): def format_price(amount, currency=u'€'): return u'{0:.2f}{1}.format(amount, currency) return dict(format_price=format_price) 上面的上下文处理器使得format_price函数在所有模板中可用: {{ format_price(0.33) }}

    日志记录

    handler = logging.FileHandler(‘flask.log’, encoding=’UTF-8′)

    1、请求之前设置requestId并记录日志

    每个URL请求之前,定义requestId并绑定到g

    @app.before_request def before_request(): g.requestId = gen_requestId() logger.info("Start Once Access, and this requestId is %s" % g.requestId)

    2、请求之后添加响应头与记录日志

    每次返回数据中,带上响应头,包含API版本和本次请求的requestId,以及允许所有域跨域访问API, 记录访问日志

    @app.after_request def add_header(response): response.headers["X-SaintIC-Media-Type"] = "saintic.v1" response.headers["X-SaintIC-Request-Id"] = g.requestId response.headers["Access-Control-Allow-Origin"] = "*" logger.info(json.dumps({ "AccessLog": { "status_code": response.status_code, "method": request.method, "ip": request.headers.get('X-Real-Ip', request.remote_addr), "url": request.url, "referer": request.headers.get('Referer'), "agent": request.headers.get("User-Agent"), "requestId": str(g.requestId), } } )) return response

    basicConfig方法可以满足你在绝大多数场景下的使用需求,但是basicConfig有一个很大的缺点。调用basicConfig其实是给root logger添加了一个handler(FileHandler ),这样当你的程序和别的使用了 logging的第三方模块一起工作时,会影响第三方模块的logger行为。这是由logger的继承特性决定的

    logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='logs/pro.log', filemode='w') logging.debug('dddddddddd')

    MySQL字符编码

    除了设置数据库的之外,由于dataset默认创建数据库和表的字符集不是utf8,所以需要自己设置,否则会中文乱码,所以需要修改表的字符集

    my.cnf [client] default-character-set=utf8 [mysqld] character-set-server=utf8 collation-server=utf8_general_ci default-storage-engine=INNODB

    表的字符集

    show create table tasks; alter table tasks convert to character set utf8;

    End.

    ,

    免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

      分享
      投诉
      首页