www.2527.com_澳门新葡8455手机版_新京葡娱乐场网址_
做最好的网站

查询语句,thinkPHP推断是还是不是修改成功

2019-06-22 01:33 来源:未知

thinkPHP中使用save方法来更新数据的
save方法的正常执行时返回值是影响的记录数,出错时返回false,返回为0和返回false在很多业务场景下都是不同的。

理解ORM框架

而当修改的内容和原有内容一致的时候返回的也就是0,通常在修改内容的表单中不进行任何修改点击修改按钮就是这种情况。
0和false是不同的,尽管作为布尔型时都代表假。0代表的是修改未修改而没有执行错误,false代表执行的时候发生了错误。
所以在判断是否修改成功时不能使用if(....->...->save())作为判断的条件,而应该使用if(....->...->save()!==false)作为判断更新执行与否的条件,同时判断值和类型是否和false匹配。

 

安装python的方法

下面在mysql命令行中举个例子:

SQL查询

ThinkPHP内置的ORM和ActiveRecord模式实现了方便的数据存取操作,而且新版增加的连贯操作功能更是让这个数据操作更加清晰,但是ThinkPHP仍然保留了原生的SQL查询和执行操作支持,为了满足复杂查询的需要和一些特殊的数据操作,SQL查询的返回值因为是直接返回的Db类的查询结果,没有做任何的处理。主要包括下面两个方法:
1、query方法

query  执行SQL查询操作

用法

query($sql,$parse=false)

参数

query(必须):要查询的SQL语句
parse(可选):是否需要解析SQL

返回值

如果数据非法或者查询错误则返回false

否则返回查询结果数据集(同select方法)

使用示例:

  1. $Model = new Model() // 实例化一个model对象 没有对应任何数据表
  2. $Model->query("select * from think_user where status=1");

如果你当前采用了分布式数据库,并且设置了读写分离的话,query方法始终是在读服务器执行,因此query方法对应的都是读操作,而不管你的SQL语句是什么。

 

2、execute方法

execute用于更新和写入数据的sql操作

用法

execute($sql,$parse=false)

参数

query(必须):要执行的SQL语句
parse(可选):是否需要解析SQL

返回值

如果数据非法或者查询错误则返回false 
否则返回影响的记录数

使用示例:

  1. $Model = new Model() // 实例化一个model对象 没有对应任何数据表
  2. $Model->execute("update think_user set name='thinkPHP' where status=1");

如果你当前采用了分布式数据库,并且设置了读写分离的话,execute方法始终是在写服务器执行,因此execute方法对应的都是写操作,而不管你的SQL语句是什么。

 

3、其他技巧
自动获取当前表名
通常使用原生SQL需要手动加上当前要查询的表名,如果你的表名以后会变化的话,那么就需要修改每个原生SQL查询的sql语句了,针对这个情况,系统还提供了一个小的技巧来帮助解决这个问题。
例如:

  1. $model = M("User");
  2. $model->query('select * from __TABLE__ where status>1');

我们这里使用了__TABLE__ 这样一个字符串,系统在解析的时候会自动替换成当前模型对应的表名,这样就可以做到即使模型对应的表名有所变化,仍然不用修改原生的sql语句。

支持连贯操作和SQL解析
新版对query和execute两个原生SQL操作方法增加第二个参数支持, 表示是否需要解析SQL (默认为false 表示直接执行sql ),如果设为true 则会解析SQL中的特殊字符串 (需要配合连贯操作)。
例如,支持 如下写法:

  1. $model->table("think_user")
  2.       ->where(array("name"=>"thinkphp"))
  3.       ->field("id,name,email")
  4.       ->query('select %FIELD% from %TABLE% %WHERE%',true);

其中query方法中的%FIELD%、%TABLE%和%WHERE%字符串会自动替换为同名的连贯操作方法的解析结果SQL,支持的替换字符串包括:

替换字符串 对应连贯操作方法
%FIELD% field
%TABLE% table
%DISTINCT% distinct
%WHERE% where
%JOIN% join
%GROUP% group
%HAVING% having
%ORDER% order
%LIMIT% limit
%UNION% union

3

http://www.cnblogs.com/kimyeee/p/7250560.html

新建个表:

动态查询

借助PHP5语言的特性,ThinkPHP实现了动态查询,包括下面几种:

方法名 说明 举例
getBy 根据某个字段的值查询数据 例如,getByName,getByEmail
getFieldBy 根据某个字段查询并返回某个字段的值 例如,getFieldByName
top 获取前多少条记录(需要高级模型支持) 例如,top8,top12

 

一、getBy动态查询
该查询方式针对数据表的字段进行查询。例如,User对象拥有id,name,email,address 等属性,那么我们就可以使用下面的查询方法来直接根据某个属性来查询符合条件的记录。

  1. $user = $User->getByName('liu21st');
  2. $user = $User->getByEmail('liu21st@gmail.com');
  3. $user = $User->getByAddress('中国深圳');

暂时不支持多数据字段的动态查询方法,请使用find方法和select方法进行查询。

 

二、getFieldBy动态查询
针对某个字段查询并返回某个字段的值,例如

  1. $user = $User->getFieldByName('liu21st','id');

表示根据用户的name获取用户的id值。

 

三、top动态查询
ThinkPHP还提供了另外一种动态查询方式,就是获取符合条件的前N条记录(和定位查询一样,也要求当前模型类必须继承高级模型类后才能使用)。例如,我们需要获取当前用户中积分大于0,积分最高的前5位用户 :

  1. $User-> where('score>80')->order('score desc')->top5();

要获取积分的前8位可以改成:

  1. $User-> where('score>80')->order('score desc')->top8();

5

概述

mysql> create table t(id int);  Query OK, 0 rows affected (0.85 sec)

子查询

新版新增了子查询支持,有两种使用方式:
1、使用select方法
当select方法的参数为false的时候,表示不进行查询只是返回构建SQL,例如:

  1. // 首先构造子查询SQL 
  2. $subQuery = $model->field('id,name')->table('tablename')->group('field')->where($where)->order('status')->select(false); 

2、使用buildSql方法

  1. $subQuery = $model->field('id,name')->table('tablename')->group('field')->where($where)->order('status')->buildSql(); 

调用buildSql方法后不会进行实际的查询操作,而只是生成该次查询的SQL语句(为了避免混淆,会在SQL两边加上括号),然后我们直接在后续的查询中直接调用。

  1. // 利用子查询进行查询 
  2. $model->table($subQuery.' a')->where()->order()->select() 

构造的子查询SQL可用于TP的连贯操作方法,例如table where等。


  • O:(objects)->类和对象。
  • R:(Relation)->关系,关系数据库中的表格。
  • M:(Mapping)->映射。

插入条数据:

作用:

mysql> insert into t(id)values(2);  Query OK, 1 row affected (0.24 sec)
  1. 可以通过类和类对象就可以操作表格中的数据
  2. 可以通过我们设计的类自动生成数据库中的表格
  3. 通过方便的配置就可以进行数据库的切换.

进行一条不改变数据的更新语句:

连接mysql数据库的方法

mysql> update t set id=2 where id=2;  Query OK, 0 rows affected (0.13 sec)  Rows matched: 1  Changed: 0  Warnings: 0

1.修改默认的使用数据库

可以注意到Changed为0,说明并未修改内容。更新语句是正常执行的,这就对应着save()返回0的时候。

进入项目的setting.py文件
DATABASES = {
'default':{
"ENGINE":"django.db.backends.mysql",
"NAME":"数据库名",
"HOST":"主机名",
"PORT":"端口"
"USER":"用户名"
"PASSWORD":"密码"
}
}
注意:django框架不会自动帮我们生成mysql数据库,所以我们需要自己去创建。
创建语句

执行一条改变数据的更新语句:

 create database test charset=utf8; #切记:指定编码

mysql> update t set id=3 where id=2;  Query OK, 1 row affected (0.14 sec)  Rows matched: 1  Changed: 1  Warnings: 0
 

Changed为1,说明这条更新语句修改了内容。对应着save()>0的时候。

2.下载连接包

再来执行一条错误的更新语句:

连接数据库时所需要的的操作
Python2--->
  Pip install python-mysql
Python3--->
  pip install pymysql
  在项目的__init__.py文件中导入 
    import pymysql
    pymysql.install _as_MySQLdb()
mysql> update t set id=2 where ida=3;  ERROR 1054 (42S22): Unknown column 'ida' in 'where clause'

3.打开booktest/models.py文件,定义模型类如下

class BookInfo(models.Model):
    # 书名字
    btitle = models.CharField(max_length=20, blank=True)

    # 出版日期
    bpub_date = models.DateField()
    # 阅读量
    bread = models.IntegerField(default=0, blank=True)
    # 评论量
    bcomment = models.IntegerField(default=0)
    # 逻辑删除
    isDelete = models.BooleanField(default=False)

    def __str__(self):
        # 使用后台管理登录时显示图书时默认会调用此方法修改,通过修改父类的方法改变显    
        # 示的内容
        return self.btitle.encode("utf-8")

  

class HeroInfo(models.Model):
    """英雄"""
    hname = models.CharField(max_length=20)
    # 性别
    hgender = models.BooleanField(default=False)
    # 说明
    hcomment = models.CharField(max_length=200)
    # 关系属性
    hbook = models.ForeignKey("BookInfo")
    # 逻辑删除
    isDelete = models.BooleanField(default=False)
  

    注:isDelete软删除标记:删除数据时不做真正的删除,而是把标记位置1表示删除,防止重要的数据丢失。

说明:

  • ForeignKey() 可以建立两个模型类之间的一对多的关系Django在生成表的时候自动生成外键,建立一对多的关系
  • 不需要定义主键列,在生成式会自动添加,并且自增

4.迁移

1.生成迁移文件=====>根据模型文件类生成创建表的语句

python manage.py makemigrations

2.执行迁移文件:根据上一步生成的语句在数据库中创建表

python manage.py migrate

注意:使用之前使用过的数据库当创建另一个新的项目时执行生成迁移文件命令后生成的迁移文件可能会与django_migrations表中的名字重名造成了运行迁移文件失败:
解决办法:将本表中的相关记录删除即可

5.向数据库中插入数据

向图书类当中添加

insert into booktest_bookinfo(btitle,bpub_date,bread,bcomment,isDelete) values
('射雕英雄传','1980-5-1',12,34,0),
('天龙八部','1986-7-24',36,40,0),
('笑傲江湖','1995-12-24',20,80,0),
('雪山飞狐','1987-11-11',58,24,0);

向英雄类当中添加

insert into booktest_heroinfo(hname,hgender,hbook_id,hcomment,isDelete) values
('郭靖',1,1,'降龙十八掌',0),
('黄蓉',0,1,'打狗棍法',0),
('黄药师',1,1,'弹指神通',0),
('欧阳锋',1,1,'蛤蟆功',0),
('梅超风',0,1,'九阴白骨爪',0),
('乔峰',1,2,'降龙十八掌',0),
('段誉',1,2,'六脉神剑',0),
('虚竹',1,2,'天山六阳掌',0),
('王语嫣',0,2,'神仙姐姐',0),
('令狐冲',1,3,'独孤九剑',0),
('任盈盈',0,3,'弹琴',0),
('岳不群',1,3,'华山剑法',0),
('东方不败',0,3,'葵花宝典',0),
('胡斐',1,4,'胡家刀法',0),
('苗若兰',0,4,'黄衣',0),
('程灵素',0,4,'医术',0),
('袁紫衣',0,4,'六合拳',0);  

打开Mysql的日志文件可以随时查看对数据库访问的语句

将一下文件当中的配置文件打开重启mysql服务

/etc/mysql/mysql.conf.d/mysqld.cnf

查看mysql的日志文件:

/var/log/mysql/mysql.log mysql

实时查看mysql文件的内容:

sudo tail -f /var/log/mysql/mysql.log 

6.通过模型类的方法操作数据库

all():返回模型类对应表格中的所有数据。QuerySet类型,查询集

# 例:查询图书所有信息。----->返回一个QuerySet对象
BookInfo.objects.all();->select * from booktest_bookinfo;

get():返回表格中满足条件的一条且只能有一条数据。----->返回一个对象

# 例:查询图书id为3的图书信息。
BookInfo.objects.get(id=3)

 

注意

  • 如果查到多条数据,则抛异常:MultipleObjectsReturned
  • 查询不到数据,则抛异常:DoesNotExi

条件查询

 

filter():参数写查询条件,返回满足条件的数据。----->返回一个QuerySet对象

格式:

  模型类属性名__条件名=值

  1. 判等 exact。

    # 例:查询编号为1的图书。 BookInfo.objects.filter(id=1) # 注意:如果tilter()没有参数即全部查到 BookInfo.objects.filter(id__exact=1) # 以上两者意思一样

 2. 模糊查询 

 # 例:查询书名包含'传'的图书。contains
    BookInfo.objects.filter(btitle__contains = "传")
    # 例:查询书名以'部'结尾的图书 endswith 开头:startswith
    BookInfo.objects.filter(btitle__endswith="天")
    BookInfo.objects.filter(btitle__startswith="天")

  3. 空查询 

 # 例:查询书名不为空的图书。isnull
    BookInfo.objects.filter(btitle__isnull=False)    

  4. 范围查询 in where id in (1,3,5)

 

 # 例:查询id编号为1或3或5的图书。
    b = BookInfo.objects.filter(id__in=[1,2,3])

  5. 比较查询 

 # 例:查询编号大于3的图书。gt、gte、lt、lte:大于、大于等于、小于、小于等于
    BookInfo.objects.filter(id__gt = 2)

  6. 日期查询

 # year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。
    #例:查询1980年发表的图书。
    BookInfo.objects.filter(bpub_date__year=1980)
    BookInfo.objects.filter(bpub_date__month = 7)
    # 例:查询1980年1月1日后发表的图。
    b = BookInfo.objects.filter(bpub_date__gt = date(1980,1,1))

  7.  exclude:返回不满足条件的数据。相当于sql语句中where部分的not关键字。----->返回一个QuerySet对象

 例:查询id不为3的图书信息。
    BookInfo.objects.exclude(id = 3)

F对象

作用:用于类属性之间的比较条件。

导入:

 

 from django.db.models import F

 

查询:

 # 查询图书阅读量大于评论量图书信息。
    BookInfo.objects.filter(bread__gt = F('bcomment'))
    # 查询图书阅读量大于2倍评论量图书信息
    BookInfo.objects.filter(bread__gt = F("bcomment")*2)

F对象

作用:用于查询时的逻辑条件。not and or,可以对Q对象进行&|~操作

导入:

    from django.db.models import Q

查询:

 from django.db.models import Q
    # 例:查询id大于3且阅读大于30的图书的信息。
    BookInfo.objects.filter(Q(id__gt = 3)&Q(bread__gt = 30))
    # 例:查询id大于3或者阅读大于30的图书的信息。
    BookInfo.objects.filter(Q(id__gt = 3)|Q(bread__gt = 30))
    # 例:查询id不等于3图书的信息。

order_by

作用:进行查询结果进行排序。----->返回一个QuerySet对象

 #例:查询所有图书的信息,按照id从小到大进行排序。
    BookInfo.objects.order_by("id")
    BookInfo.objects.all().order_by("id")
    # 以上两种都可以--默认为升序
    # 例:查询所有图书的信息,按照id从大到小进行排序。
    BookInfo.objects.all().order_by("-id")
    # 降序
    # 例:把id大于3的图书信息按阅读量从大到小排序显示;
    BookInfo.objects.filter(id__gt = 3).order_by("-bread")

聚合函数

作用:对查询结果进行聚合操作。----->返回一个字典

导入:

 

        from django.db.models import sum count max min avg   

 

aggregate:调用这个函数来使用聚合。

 # 例:查询所有图书的数目。
    BookInfo.objects.aggregate(Count("id"))
    >>>>{'id__count': 4}
    # 注意:返回值为一个字典 key值为查询时的条件字段名_聚合操作===>字段名_聚合操作
    #例:查询所有图书阅读量的总和。
    BookInfo.objects.aggregate(Sum("bread"))
    {'bread__sum': 126}

count

作用:统计满足条件数据的总数目。----->返回一个值

 

 # 例:统计id大于3的所有图书的数目。
    BookInfo.objects.filter(id__gt = 3).count()

 

exists

作用:判断查询集中是否有数据,如果有则返回True,没有则返回False。

 

 # 例:判断查询集b当中是否有数据
    b = BookInfo.objects.all()
    b.exists()

 

查询支持列表生成式

 

 # 例:查询所有书的id
    [book.id for book in BookInfo.objects.all()]

 

7.数据的插入,更新,和删除

 

调用一个模型类对象的save方法的时候就可以实现对模型类对应数据表的插入和更新。
调用一个模型类对象的delete方法的时候就可以实现对模型类对应数据表数据的删除。

插入

 

----->创建模型类的对象

b = BookInfo()

----->定义对象的属性并赋值

b.btitle = "某某"
b.bpub_date = date(1990,10,11)

----->保存数据

b.save() # 保存到数据库当中

修改

查询表中id为1的数据

b = BookInfo.objects.get(id=1)

修改上面的属性

b.btitle = "某某某"
b.save() # 保存到数据库当中

删除

b.delete() # 对象.delete()

8.限制查询集的操作-->允许切片操作

例:

b = BookInfo.objects.all()
b[0]

返回的结果: <BookInfo: [Bad Unicode data]>

获取前三个数据
b[0:3]

注意: 通过切片操作访问时切片超出时会报indexerror错误
也可以通过以下方式获取:

b[0:2].get()

当有多条数据或没有数据时会出错

error:DoesNotExist或MultipleObjectsReturned

注意:对一个查询集进行切片操作会产生一个新的查询集,下标不允许为负数。

9.关联查询

关联查询(一对多)
在一对多关系中,一对应的类我们把它叫做一类,多对应的那个类我们把它叫做多类,我们把多类中定义的建立关联的类属性叫做关联属性。

通过对象实现关联查询:

# 例:查询图书id为1的所有英雄的信息。
b = BookInfo.objects.get(id=1)
b.heroinfo_set.all()
# 例:查询id为1的英雄所属图书信息。
h = HeroInfo.objects.get(id=1)  
# 获取图书时有三种方法
h.hbook-----获取对应书的对象
h.hbook.id-----获取对应书的id
h.hbook_id-----获取对应书的id

格式:
  由一类的对象查询多类的时候:
    一类的对象.多类名小写_set.all() #查询所用数据
  由多类的对象查询一类的时候:
    多类的对象.关联属性 #查询多类的对象对应的一类的对象
  由多类的对象查询一类对象的id时候:
    多类的对象. 关联属性_id
总结:通过对象实现查询的时候先获取条件的对象,然后再查询最终查询的内容

通过模型类实现关联查询:

 

# 例:查询图书,要求图书中英雄的描述包含'八'。
BookInfo.objects.filter(heroinfo__hcomment__contains= " 八")
# 例:查询图书,要求图书中的英雄的id大于3.
BookInfo.objects.filter(heroinfo__id__gt = 3)
# 例:查询书名为“天龙八部”的所有英雄。
HeroInfo.objects.filter(hbook__btitle="天龙八部")

格式:

 

  通过多类的条件查询一类的数据:
    一类名.objects.filter(多类名小写__多类属性名__条件名)
  通过一类的条件查询多类的数据:
    多类名.objects.filter(关联属性__一类属性名__条件名)

总结:当一类为条件的时候,多类当中有关联属性,直接拿关联属性即可找到一类对应属性的条件

*  *1.显示什么就先写什么
  2.判断条件为一类还是多类,如果条件为多类--通过类名找,如果条件为一类--通过关联属性查
  3.显示什么就先写什么,Django框架会遍历先写的模型类里的内容如果条件为一类的此时先写的模型类当中有关联属性,此时就可以根据关联属性查找

 

发生错误,对应save()为false的时候。


TAG标签:
版权声明:本文由澳门新葡8455手机版发布于www.2527.com,转载请注明出处:查询语句,thinkPHP推断是还是不是修改成功