1. python + django 多表联合查询方法求教
先让我们回忆一下在第五章里的关于书本(book)的数据模型:1fromdjango.dbimportmodelsclassPublisher(models.Model):name=models.CharField(max_length=30)address=models.CharField(max_length=50)city=models.CharField(max_length=60)state_province=models.CharField(max_length=30)country=models.CharField(max_length=50)website=models.URLField()def__unicode__(self):returnself.nameclassAuthor(models.Model):first_name=models.CharField(max_length=30)last_name=models.CharField(max_length=40)email=models.EmailField()def__unicode__(self):returnu'%s%s'%(self.first_name,self.last_name)classBook(models.Model):title=models.CharField(max_length=100)authors=models.ManyToManyField(Author)publisher=models.ForeignKey(Publisher)publication_date=models.DateField()def__unicode__(self):returnself.title如我们在第5章的讲解,获取数据库对象的特定字段的值只需直接使用属性。例如,要确定ID为50的书本的标题,我们这样做:>>>frommysite.books.modelsimportBook>>>b=Book.objects.get(id=50)>>>b.titleu'TheDjangoBook'但是,在之前有一件我们没提及到的是表现为ForeignKey或ManyToManyField的关联对象字段,它们的作用稍有不同。访问外键(ForeignKey)值当你获取一个ForeignKey字段时,你会得到相关的数据模型对象。例如:>>>b=Book.objects.get(id=50)>>>b.publisher>>>b.publisher.websiteu'http://www.apress.com/'对于用``ForeignKey``来定义的关系来说,在关系的另一端也能反向的追溯回来,只不过由于不对称性的关系而稍有不同。通过一个``publisher``对象,直接获取books,用publisher.book_set.all(),如下:>>>p=Publisher.objects.get(name='ApressPublishing')>>>p.book_set.all()[,,]实际上,book_set只是一个QuerySet(参考第5章的介绍),所以它可以像QuerySet一样,能实现数据过滤和分切,例如:1>>>p=Publisher.objects.get(name='ApressPublishing')>>>p.book_set.filter(name__icontains='django')[,]属性名称book_set是由模型名称的小写(如book)加_set组成的。访问多对多值(Many-to-ManyValues)多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。例如,这里是如何查看书籍的作者:>>>b=Book.objects.get(id=50)>>>b.authors.all()[,]>>>b.authors.filter(first_name='Adrian')[]>>>b.authors.filter(first_name='Adam')[]反向查询也可以。要查看一个作者的所有书籍,使用author.book_set,就如这样:>>>a=Author.objects.get(first_name='Adrian',last_name='Holovaty')>>>a.book_set.all()[,]这里,就像使用ForeignKey字段一样,属性名book_set是在数据模型(model)名后追加_set。更改数据库模式(DatabaseSchema)3在我们在第5章介绍syncdb这个命令时,我们注意到syncdb仅仅创建数据库里还没有的表,它并不对你数据模型的修改进行同步,也不处理数据模型的删除。如果你新增或修改数据模型里的字段,或是删除了一个数据模型,你需要手动在数据库里进行相应的修改。这段将解释了具体怎么做:当处理模型修改的时候,将Django的数据库层的工作流程铭记于心是很重要的。如果模型包含一个未曾在数据库里建立的字段,Django会报出错信息。当你第一次用Django的数据库API请求表中不存在的字段时会导致错误(就是说,它会在运行时出错,而不是编译时)。3Django不关心数据库表中是否存在未在模型中定义的列。Django不关心数据库中是否存在未被模型表示的表格。1改变模型的模式架构意味着需要按照顺序更改Python代码和数据库。添加字段1当要向一个产品设置表(或者说是model)添加一个字段的时候,要使用的技巧是利用Django不关心表里是否包含model里所没有的列的特性。策略就是现在数据库里加入字段,然后同步Django的模型以包含新字段。3然而这里有一个鸡生蛋蛋生鸡的问题,由于要想了解新增列的SQL语句,你需要使用Django的manage.pysqlall命令进行查看,而这又需要字段已经在模型里存在了。(注意:你并不是非得使用与Django相同的SQL语句创建新的字段,但是这样做确实是一个好主意,它能让一切都保持同步。)3这个鸡-蛋的问题的解决方法是在开发者环境里而不是发布环境里实现这个变化。(你正使用的是测试/开发环境,对吧?)下面是具体的实施步骤。首先,进入开发环境(也就是说,不是在发布环境里):在你的模型里添加字段。运行manage.pysqlall[yourapp]来测试模型新的CREATETABLE语句。注意为新字段的列定义。开启你的数据库的交互命令界面(比如,psql或mysql,或者可以使用manage.pydbshell)。执行ALTERTABLE语句来添加新列。使用Python的manage.pyshell,通过导入模型和选中表单(例如,MyModel.objects.all()[:5])来验证新的字段是否被正确的添加,如果一切顺利,所有的语句都不会报错。3然后在你的产品服务器上再实施一遍这些步骤。启动数据库的交互界面。5执行在开发环境步骤中,第三步的ALTERTABLE语句。将新的字段加入到模型中。如果你使用了某种版本控制工具,并且在第一步中,已经提交了你在开发环境上的修改,现在,可以在生产环境中更新你的代码了(例如,如果你使用Subversion,执行svnupdate。重新启动Webserver,使修改生效。让我们实践下,比如添加一个num_pages字段到第五章中Book模型。首先,我们会把开发环境中的模型改成如下形式:classBook(models.Model):title=models.CharField(max_length=100)authors=models.ManyToManyField(Author)publisher=models.ForeignKey(Publisher)publication_date=models.DateField()**num_pages=models.IntegerField(blank=True,null=True)**def__unicode__(self):returnself.title
2. Django怎么算列的总数
这个看在哪里算了。如果是在服务器端算,和一般的python运算是一样的啊。或者直接执行SQL语句。
3. python + django 多表联合查询方法求教
先让我们回忆一下在第五章里的关于书本(book)的数据模型:
1
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return self.name
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
def __unicode__(self):
return self.title
如我们在第5章的讲解,获取数据库对象的特定字段的值只需直接使用属性。 例如,要确定ID为50的书本的标题,我们这样做:
>>> from mysite.books.models import Book
>>> b = Book.objects.get(id=50)
>>> b.title
u'The Django Book'
但是,在之前有一件我们没提及到的是表现为ForeignKey 或 ManyToManyField的关联对象字段,它们的作用稍有不同。
访问外键(Foreign Key)值
当你获取一个ForeignKey 字段时,你会得到相关的数据模型对象。 例如:
>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'
对于用`` ForeignKey``
来定义的关系来说,在关系的另一端也能反向的追溯回来,只不过由于不对称性的关系而稍有不同。 通过一个`` publisher`` 对象,直接获取
books ,用 publisher.book_set.all() ,如下:
>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]
实际上,book_set 只是一个 QuerySet(参考第5章的介绍),所以它可以像QuerySet一样,能实现数据过滤和分切,例如:
1
>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.filter(name__icontains='django')
[<Book: The Django Book>, <Book: Pro Django>]
属性名称book_set是由模型名称的小写(如book)加_set组成的。
访问多对多值(Many-to-Many Values)
多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。 例如,这里是如何查看书籍的作者:
>>> b = Book.objects.get(id=50)
>>> b.authors.all()
[<Author: Adrian Holovaty>, <Author: Jacob Kaplan-Moss>]
>>> b.authors.filter(first_name='Adrian')
[<Author: Adrian Holovaty>]
>>> b.authors.filter(first_name='Adam')
[]
反向查询也可以。 要查看一个作者的所有书籍,使用author.book_set ,就如这样:
>>> a = Author.objects.get(first_name='Adrian', last_name='Holovaty')
>>> a.book_set.all()
[<Book: The Django Book>, <Book: Adrian's Other Book>]
这里,就像使用 ForeignKey字段一样,属性名book_set是在数据模型(model)名后追加_set。
更改数据库模式(Database Schema)
3
在我们在第5章介绍 syncdb 这个命令时, 我们注意到 syncdb仅仅创建数据库里还没有的表,它 并不 对你数据模型的修改进行同步,也不处理数据模型的删除。 如果你新增或修改数据模型里的字段,或是删除了一个数据模型,你需要手动在数据库里进行相应的修改。 这段将解释了具体怎么做:
当处理模型修改的时候,将Django的数据库层的工作流程铭记于心是很重要的。
如果模型包含一个未曾在数据库里建立的字段,Django会报出错信息。 当你第一次用Django的数据库API请求表中不存在的字段时会导致错误(就是说,它会在运行时出错,而不是编译时)。
3
Django不关心数据库表中是否存在未在模型中定义的列。
Django不关心数据库中是否存在未被模型表示的表格。
1
改变模型的模式架构意味着需要按照顺序更改Python代码和数据库。
添加字段
1
当要向一个产品设置表(或者说是model)添加一个字段的时候,要使用的技巧是利用Django不关心表里是否包含model里所没有的列的特性。 策略就是现在数据库里加入字段,然后同步Django的模型以包含新字段。
3
然而 这里有一个鸡生蛋蛋生鸡的问题 ,由于要想了解新增列的SQL语句,你需要使用Django的
manage.py sqlall命令进行查看 ,而这又需要字段已经在模型里存在了。 (注意:你并 不是非得使用与Django相同的SQL语句创建新的字段,但是这样做确实是一个好主意 ,它能让一切都保持同步。)
3
这个鸡-蛋的问题的解决方法是在开发者环境里而不是发布环境里实现这个变化。 (你正使用的是测试/开发环境,对吧?)下面是具体的实施步骤。
首先,进入开发环境(也就是说,不是在发布环境里):
在你的模型里添加字段。
运行 manage.py sqlall [yourapp] 来测试模型新的 CREATE TABLE 语句。 注意为新字段的列定义。
开启你的数据库的交互命令界面(比如, psql 或mysql , 或者可以使用
manage.py dbshell )。 执行 ALTER TABLE 语句来添加新列。
使用Python的manage.py shell,通过导入模型和选中表单(例如,
MyModel.objects.all()[:5] )来验证新的字段是否被正确的添加 ,如果一切顺利,所有的语句都不会报错。
3
然后在你的产品服务器上再实施一遍这些步骤。
启动数据库的交互界面。
5
执行在开发环境步骤中,第三步的ALTER TABLE语句。
将新的字段加入到模型中。 如果你使用了某种版本控制工具,并且在第一步中,已经提交了你在开发环境上的修改,现在,可以在生产环境中更新你的代码了(例如,如果你使用Subversion,执行svn update。
重新启动Web server,使修改生效。
让我们实践下,比如添加一个num_pages字段到第五章中Book模型。首先,我们会把开发环境中的模型改成如下形式:
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
**num_pages = models.IntegerField(blank=True, null=True)**
def __unicode__(self):
return self.title
4. django 获取数据表中 有多少条数据
Django 拥有自己的ORM模块。
通俗来讲其过程如下:
在Django中写Python 代码
将Python代码通过ORM模块转换成SQL语句
通过类似pymysql等数据库操作模块,使用SQL语句,前往数据库访问数据
上述过程的反方向
获取Python格式的数据
5. django 过滤器 什么意思
关于django过滤器,
过滤器,变量的显示形式的改变
一、形式:小写
{{ name | lower }}
二、串联:先转义文本到HTML,再转换每行到 <p> 标签
{{ my_text|escape|linebreaks }}
三、过滤器的参数
显示前30个字
{{ bio | truncatewords:"30" }}
格式化
{{ pub_date | date:"F j, Y" }}
过滤器列表
{{ 123|add:"5" }} 给value加上一个数值
{{ "AB'CD"|addslashes }} 单引号加上转义号,一般用于输出到javascript中
{{ "abcd"|capfirst }} 第一个字母大写
{{ "abcd"|center:"50" }} 输出指定长度的字符串,并把值对中
{{ "123spam456spam789"|cut:"spam" }} 查找删除指定字符串
{{ value|date:"F j, Y" }} 格式化日期
{{ value|default:"(N/A)" }} 值不存在,使用指定值
{{ value|default_if_none:"(N/A)" }} 值是None,使用指定值
{{ 列表变量|dictsort:"数字" }} 排序从小到大
{{ 列表变量|dictsortreversed:"数字" }} 排序从大到小
{% if 92|divisibleby:"2" %} 判断是否整除指定数字
{{ string|escape }} 转换为html实体
{{ 21984124|filesizeformat }} 以1024为基数,计算最大值,保留1位小数,增加可读性
{{ list|first }} 返回列表第一个元素
{{ "ik23hr&jqwh"|fix_ampersands }} &转为&
{{ 13.414121241|floatformat }} 保留1位小数,可为负数,几种形式
{{ 13.414121241|floatformat:"2" }} 保留2位小数
{{ 23456 |get_digit:"1" }} 从个位数开始截取指定位置的1个数字
{{ list|join:", " }} 用指定分隔符连接列表
{{ list|length }} 返回列表个数
{% if 列表|length_is:"3" %} 列表个数是否指定数值
{{ "ABCD"|linebreaks }} 用新行用<p> 、 <br /> 标记包裹
{{ "ABCD"|linebreaksbr }} 用新行用<br /> 标记包裹
{{ 变量|linenumbers }} 为变量中每一行加上行号
{{ "abcd"|ljust:"50" }} 把字符串在指定宽度中对左,其它用空格填充
{{ "ABCD"|lower }} 小写
{% for i in "1abc1"|make_list %}ABCDE,{% endfor %} 把字符串或数字的字符个数作为一个列表
{{ "abcdefghijklmnopqrstuvwxyz"|phone2numeric }} 把字符转为可以对应的数字??
{{ 列表或数字|pluralize }} 单词的复数形式,如列表字符串个数大于1,返回s,否则返回空串
{{ 列表或数字|pluralize:"es" }} 指定es
{{ 列表或数字|pluralize:"y,ies" }} 指定ies替换为y
{{ object|pprint }} 显示一个对象的值
{{ 列表|random }} 返回列表的随机一项
{{ string|removetags:"br p div" }} 删除字符串中指定html标记
{{ string|rjust:"50" }} 把字符串在指定宽度中对右,其它用空格填充
{{ 列表|slice:":2" }} 切片
{{ string|slugify }} 字符串中留下减号和下划线,其它符号删除,空格用减号替换
{{ 3|stringformat:"02i" }} 字符串格式,使用Python的字符串格式语法
{{ "E<A>A</A>B<C>C</C>D"|striptags }} 剥去[X]HTML语法标记
{{ 时间变量|time:"P" }} 日期的时间部分格式
{{ datetime|timesince }} 给定日期到现在过去了多少时间
{{ datetime|timesince:"other_datetime" }} 两日期间过去了多少时间
{{ datetime|timeuntil }} 给定日期到现在过去了多少时间,与上面的区别在于2日期的前后位置。
{{ datetime|timeuntil:"other_datetime" }} 两日期间过去了多少时间
{{ "abdsadf"|title }} 首字母大写
{{ "A B C D E F"|truncatewords:"3" }} 截取指定个数的单词
{{ "<a>1<a>1<a>1</a></a></a>22<a>1</a>"|truncatewords_html:"2" }} 截取指定个数的html标记,并补完整
<ul>{{ list|unordered_list }}</ul> 多重嵌套列表展现为html的无序列表
{{ string|upper }} 全部大写
<a href="{{ link|urlencode }}">linkage</a> url编码
{{ string|urlize }} 将URLs由纯文本变为可点击的链接。(没有实验成功)
{{ string|urlizetrunc:"30" }} 同上,多个截取字符数。(同样没有实验成功)
{{ "B C D E F"|wordcount }} 单词数
{{ "a b c d e f g h i j k"|wordwrap:"5" }} 每指定数量的字符就插入回车符
{{ boolean|yesno:"Yes,No,Perhaps" }} 对三种值的返回字符串,对应是 非空,空,None
6. django查询数据量总数问题
AttributeCount = UrlList.objects.filter(url_source_id__in=[2,3,5,6,7,8]).count()
return render_to_response('main.html', {'AttributeCount':AttributeCount})
这样试试吧
7. django 如何用formset 显示数据库里的经过 过滤的数据用户资料和修改资料
formset是一个困惑的东西。用好了可以简化代码,减少template和view的工作量。不过初学的时候,可以自己直接写html代码更直观些。
formset似乎与数据库并没有直接的关系。查询数据库的class.objects.query里,使用select语句什么都能过滤。当然也可以用get , all ,filter等函数,在函数的入口里加入等于的过滤条件,这个过滤比较的简单的。
8. django先exclude 再filter
Model.objects.exclude(xxxx=xx).filter(xxxx=xx)
这样就可以了,可以连贯操作的。。。
filter里面也可以多个filter(xxxx=xx,aaa=aa,bbb=bb)
9. 如何有效的遍历django的QuerySet
最近做了一个小的需求,在django模型中通过前台页面的表单的提交
(post),后台对post的参数进行解析,通过models模型查询MySQL,将数据结构进行加工,返回到前台页面进行展示。由于对django中
QuerySet特性的不熟悉,所以测试过程中发现了很多问题。
开始的阶段没有遇到什么问题,我们举例,在models有一张员工表
employee,对应的表结构中,postion列表示员工职位,前台post过来的参数赋给position,加上入职时间、离职时间,查询操作通过
models.filter(position=params)完成,获取的员工信息内容由QuerySet和当前展示页与每页展示的记录数进行简单的计
算,返回给前台页面进行渲染展示。编码如下:
1 def get_employees(position, start, end):
2 return employee.objects.filter(alert_time__lt=end,alert_time__gt=start).filter(position__in=position)
3
4
5 @login_required
6 def show(request):
7 if not validate(request):
8 return render_to_response('none.html',
9 context_instance=RequestContext(request, 'msg':'params error')
10 )
11
12 position = request.REQUEST.get('position')
13 time_range = request.REQUEST.get('time')
14 start, end = time_range[0], time_range[1]
15
16 num_per_page, page_num = get_num(request)
17 all_employees = get_employees(position, start, end)
18 # 根据当前页与每页展示的记录数,取到正确的记录
19 employees = employees_events[(page_num-1)*num_per_page:page_num*num_per_page]
20
21 return render_to_response('show_employees.html',
22 context_instance=RequestContext(
23 request,
24 'employees': employees,
25 'num_per_page': num_per_page,
26 'page_num':page_num,
27 'page_options' : [50, 100, 200]
28 )
29 )
运行之后可以正确的对所查询的员工信息进行展示,并且查询速度很快。
employee表中存放着不同职位的员工信息,不同类型的详细内容也不相同,假设employees有一列名为infomation,存储的是员工的详
细信息,infomation = {'age': 33, 'gender': 'male', 'nationality': 'German',
'degree': 'doctor', 'motto': 'just do
it'},现在的需求是要展示出分类更细的员工信息,前台页面除了post职位、入职离职时间外,还会对infomation中的内容进行筛选,这里以查
询中国籍的设计师为例,在之前的代码基础上,需要做一些修改。员工信息表employee存放于MySQL中,而MySQL为ORM数据库,它并未提供类
似mongodb一样更为强大的聚合函数,所以这里不能通过objects提供的方法进行filter,一次性将所需的数据获取出来,那么需要对type
进行过滤后的数据,进行二次遍历,通过information来确定当前记录是否需要返回展示,在展示过程中,需要根据num_per_page和
page_num计算出需要展示数据起始以及终止位置。
1 def get_employees(position, start, end):
2 return employee.objects.filter(alert_time__lt=end,alert_time__gt=start).filter(position__in=position)
3
4
5 def filter_with_nation(all_employees, nationality, num_per_page, page_num):
6 result = []
7
8 pos = (page_num-1)*num_per_page
9 cnt = 0
10 start = False
11 for employee in all_employees:
12 info = json.loads(employee.information)
13 if info.nationality != nationality:
14 continue
15
16 # 获取的数据可能并不是首页,所以需要先跳过前n-1页
17 if cnt == pos:
18 if start:
19 break
20 cnt = 0
21 pos = num_per_page
22 start = True
23
24 if start:
25 result.append(employee)
26
27 return employee
28
29
30 @login_required
31 def show(request):
32 if not validate(request):
33 return render_to_response('none.html',
34 context_instance=RequestContext(request, 'msg':'params error')
35 )
36
37 position = request.REQUEST.get('position')
38 time_range = request.REQUEST.get('time')
39 start, end = time_range[0], time_range[1]
40
41 num_per_page, page_num = get_num(request)
42 all_employees = get_employees(position, start, end)
43
44 nationality = request.REQUEST.get('nationality')
45
46 employees = filter_with_nation(all_employees, num_per_page, page_num)
47
48 return render_to_response('show_employees.html',
49 context_instance=RequestContext(
50 request,
51 'employees': employees,
52 'num_per_page': num_per_page,
53 'page_num':page_num,
54 'page_options' : [50, 100, 200]
55 )
56 )
当编码完成之后,在数据employee表数据很小的情况下测试并未发现问
题,而当数据量非常大,并且查询的数据很少时,代码运行非常耗时。我们设想,这是一家规模很大的跨国公司,同时人员的流动量也很大,所以employee
表的数据量很庞大,而这里一些来自于小国家的员工并不多,比如需要查询国籍为梵蒂冈的员工时,前台页面进入了无尽的等待状态。同时,监控进程的内存信息,
发现进程的内存一直在增长。毫无疑问,问题出现在filter_with_nation这个函数中,这里逐条遍历了employee中的数据,并且对每条
数据进行了解析,这并不是高效的做法。
在网上查阅了相关资料,了解到:
1 Django的queryset是惰性的,使用filter语句进行查询,实际上并没有运行任何的要真正从数据库获得数据
2 只要你查询的时候才真正的操作数据库。会导致执行查询的操作有:对QuerySet进行遍历queryset,切片,序列化,对 QuerySet 应用 list()、len()方法,还有if语句
3 当第一次进入循环并且对QuerySet进行遍历时,Django从数据库中获取数据,在它返回任何可遍历的数据之前,会在内存中为每一条数据创建实例,而这有可能会导致内存溢出。
上面的原来很好的解释了代码所造成的现象。那么如何进行优化是个问题,网上有
说到当QuerySet非常巨大时,为避免将它们一次装入内存,可以使用迭代器iterator()来处理,但对上面的代码进行修改,遍历时使用
employee.iterator(),而结果和之前一样,内存持续增长,前台页面等待,对此的解释是:using iterator()
will save you some memory by not storing the result of the cache
internally (though not necessarily on PostgreSQL!); but will still
retrieve the whole objects from the database。
这里我们知道不能一次性对QuerySet中所有的记录进行遍历,那么只能对
QuerySet进行切片,每次取一个chunk_size的大小,遍历这部分数据,然后进行累加,当达到需要的数目时,返回满足的对象列表,这里修改下
filter_with_nation函数:
1 def filter_with_nation(all_employees, nationality, num_per_page, page_num):
2 result = []
3
4 pos = (page_num-1)*num_per_page
5 cnt = 0
6 start_pos = 0
7 start = False
8 while True:
9 employees = all_employees[start_pos:start_pos+num_per_page]
10 start_pos += num_per_page
11
12 for employee in employees:
13 info = json.loads(employee.infomation)
14 if info.nationality != nationality:
15 continue
16
17 if cnt == pos:
18 if start:
19 break
20 cnt = 0
21 pos = num_per_page
22 start = True
23
24 if start:
25 result.append(opt)
26
27 cnt += 1
28
29 if cnt == num_per_page or not events:
30 break
31
32 return result
运行上述代码时,查询的速度更快,内存也没有明显的增长,得到效果不错的优
化。这篇文章初衷在于记录自己对django中queryset的理解和使用,而对于文中的例子,其实正常业务中,如果需要记录员工详细的信息,最好对
employee表进行扩充,或者建立一个字表,存放详细信息,而不是将所有信息存放入一个字段中,避免在查询时的二次解析。