char和varchar区别
1, char的长度是不可变的,而varchar在长度是可变的(当然是在你设定的最大的长度范围内可变)
2, 定义一个char[10]和varchar[10],如果存进去的是‘abcd’,那么char所占的长度依然为10,除了字符‘abcd’外,后面跟六个空格,而varchar就立马把长度变为4了(4+1,后面解释),取数据的时候,char类型的要用trim()去掉多余的空格,而varchar是不需要的。
3, char的存取数度还是要比varchar要快得多,因为其长度固定,方便程序的存储与查找;但是char也为此付出的是空间的代价,因为其长度固定,所以难免会有多余的空格占位符占据空间。varchar是可变长度.由于是可变长度,因此存储的是实际字符串再加上一个记录字符串长度的字节。
4,VARCHAR虽然比CHAR节省空间,但是如果一个VARCHAR列经常被修改,而且每次被修改的数据的长度不同,这会引起‘行迁移’(Row Migration)现象,而这造成多余的I/O,是数据库设计和调整中要尽力避免的,在这种情况下用CHAR代替VARCHAR2会更好一些。
综上:各有千秋。
django内部已经支持的字段类型:
从里面看字符串类型的全部都是varchar而没有char,所以我们有时需要自定义char字段类型。
data_types = {
'AutoField': 'NUMBER(11) GENERATED BY DEFAULT ON NULL AS IDENTITY',
'BigAutoField': 'NUMBER(19) GENERATED BY DEFAULT ON NULL AS IDENTITY',
'BinaryField': 'BLOB',
'BooleanField': 'NUMBER(1)',
'CharField': 'NVARCHAR2(%(max_length)s)',
'DateField': 'DATE',
'DateTimeField': 'TIMESTAMP',
'DecimalField': 'NUMBER(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'INTERVAL DAY(9) TO SECOND(6)',
'FileField': 'NVARCHAR2(%(max_length)s)',
'FilePathField': 'NVARCHAR2(%(max_length)s)',
'FloatField': 'DOUBLE PRECISION',
'IntegerField': 'NUMBER(11)',
'BigIntegerField': 'NUMBER(19)',
'IPAddressField': 'VARCHAR2(15)',
'GenericIPAddressField': 'VARCHAR2(39)',
'NullBooleanField': 'NUMBER(1)',
'OneToOneField': 'NUMBER(11)',
'PositiveIntegerField': 'NUMBER(11)',
'PositiveSmallIntegerField': 'NUMBER(11)',
'SlugField': 'NVARCHAR2(%(max_length)s)',
'SmallIntegerField': 'NUMBER(11)',
'TextField': 'NCLOB',
'TimeField': 'TIMESTAMP',
'URLField': 'VARCHAR2(%(max_length)s)',
'UUIDField': 'VARCHAR2(32)',
}
字段类型的父类Field源码分析:
把类变量删掉,把没注释的方法删掉,看似不重要的方法也删掉,重点看注释多的方法,尤其是关注‘override’重载和‘custom ’用户自定义这两个关键词的方法。
@total_ordering
class Field(RegisterLookupMixin):
def __init__(self, verbose_name=None, name=None, primary_key=False,
max_length=None, unique=False, blank=False, null=False,
db_index=False, rel=None, default=NOT_PROVIDED, editable=True,
serialize=True, unique_for_date=None, unique_for_month=None,
unique_for_year=None, choices=None, help_text='', db_column=None,
db_tablespace=None, auto_created=False, validators=(),
error_messages=None):
self.name = name
self.verbose_name = verbose_name # May be set by set_attributes_from_name
self._verbose_name = verbose_name # Store original for deconstruction
self.primary_key = primary_key
self.max_length, self._unique = max_length, unique
self.blank, self.null = blank, null
self.remote_field = rel
self.is_relation = self.remote_field is not None
self.default = default
self.editable = editable
self.serialize = serialize
self.unique_for_date = unique_for_date
self.unique_for_month = unique_for_month
self.unique_for_year = unique_for_year
if isinstance(choices, collections.abc.Iterator):
choices = list(choices)
self.choices = choices or []
self.help_text = help_text
self.db_index = db_index
self.db_column = db_column
self._db_tablespace = db_tablespace
self.auto_created = auto_created
# Adjust the appropriate creation counter, and save our local copy.
if auto_created:
self.creation_counter = Field.auto_creation_counter
Field.auto_creation_counter -= 1
else:
self.creation_counter = Field.creation_counter
Field.creation_counter += 1
self._validators = list(validators) # Store for deconstruction later
messages = {}
for c in reversed(self.__class__.__mro__):
messages.update(getattr(c, 'default_error_messages', {}))
messages.update(error_messages or {})
self._error_messages = error_messages # Store for deconstruction later
self.error_messages = messages
def db_type(self, connection):
"""
Return the database column data type for this field, for the provided
connection.返回该字段的数据库列数据类型
"""
# The default implementation of this method looks at the
# backend-specific data_types dictionary, looking up the field by its
# "internal type".该方法的默认实现查看后端特定的data_types字典,根据其“内部类型”查找字段
#
# A Field class can implement the get_internal_type() method to specify
# which *preexisting* Django Field class it's most similar to -- i.e.,
# a custom field might be represented by a TEXT column type, which is
# the same as the TextField Django field type, which means the custom
# field's get_internal_type() returns 'TextField'.
#字段类可以实现get_internal_type()方法来指定它最类似于哪个*预先存在的* Django字段类。,
#例如:自定义字段可能由文本列类型表示,它与TextField Django字段类型
#相同,这意味着自定义字段的get_internal_type()将返回“TextField”。
#
# But the limitation of the get_internal_type() / data_types approach
# is that it cannot handle database column types that aren't already
# mapped to one of the built-in Django field types. In this case, you
# can implement db_type() instead of get_internal_type() to specify
# exactly which wacky database column type you want to use.
# 但是get_internal_type() / data_types方法的限制是,它不能处理尚未映射到内置Django
# 字段类型之一的数据库列类型。在这种情况下,你可以实现db_type(),而不是get_internal_type(),
# 以明确指定你想要使用哪种古怪的数据库列类型
data = self.db_type_parameters(connection)
try:
return connection.data_types[self.get_internal_type()] % data
except KeyError:
return None
def db_parameters(self, connection):
"""
Extension of db_type(), providing a range of different return values
(type, checks). This will look at db_type(), allowing custom model
fields to override it.
扩展db_type(),提供一系列不同的返回值(类型和检查)。这将取决于db_type(),允许自定义模型字段覆盖它
"""
type_string = self.db_type(connection)
check_string = self.db_check(connection)
return {
"type": type_string,
"check": check_string,
}
自定义char字段类型示例:
from django.db import models
# Create your models here.
class CCharField(models.Field):
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super(CCharField, self).__init__(max_length=max_length, *args, **kwargs)
def db_type(self, connection):
return 'char(%s)' %(self.max_length)
class Users(models.Model):
username = models.CharField(max_length=20)
pwd = CCharField(max_length=20)
更精简的 自定义char字段类型示例
from django.db import models
# Create your models here.
class CCharField(models.Field):
def db_type(self, connection):
return 'char(%s)' %(self.max_length)
class Users(models.Model):
username = models.CharField(max_length=20)
pwd = CCharField(max_length=20)