博客已持续运行3608天
ー切鉯叛縌ゐ目的的俳疰橊都寔悻ㄢ蚤擾!!
进入博客
不要停下脚步哪怕前方没有光
“IP地址”就相当于“电话号码”,而Internet中的路由器,就相当于电信局的“程控式交换机”。

点分十进制数表示的IPv4地址被分为几类,以适应大型、中型、小型的网络。这些类的不同之处在于不同类别的网络地址所占位数。

**IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”(也就是4个字节)。IP地址通常用“点分十进制”表示成(a.b.c.d)的形式,**其中,a,b,c,d都是0~255之间的十进制整数。例:点分十进IP地址(100.4.5.6),实际上是32位二进制数(01100100.00000100.00000101.00000110)。

1. IP地址=网络地址+主机地址
按照起始字符的不同,IP地址可以分为A、B、C、D、E类地址。

A类地址:0(开头)+7位(网络地址)+24位(主机地址)
B类地址:10(开头)+14位(网络地址)+16位(主机地址)
C类地址:110(开头)+21位(网络地址)+8位(主机地址)
D类 以1110开始 用于组播
E类 以11110开始 用于科研保留

范围上划分有些要注意的:
A类 从1.0.0.0 到126.255.255.255
B类 从128.0.0.0到191.255.255.255
C类 从192.0.0.0到223.255.255.255
其中127.x.x.x段地址空间是被保留的回环地址

D类 以1110开始 用于组播
E类 以11110开始 用于科研保留

A类地址具有24为主机地址,因此应用于大规模环境
C类地址具有8位主机地址,应用于规模较小的网络
B类居中

在A、B、C类地址中,都存在一部分用于内网(局域网)的IP地址(私有地址)

>     A类的私有地址: 10.0.0.0 ~ 10.255.255.255
>     
>     B类的私有地址: 172.16.0.0 ~ 172.31.255.255  
>     (网络号范围: 10101010 00010000 ~ 10101010 00011111)
>     
>     C类的私有地址: 192.168.0.0 ~ 192.168.255.255
>     (网络号范围: 11000000 10101000 00000000 ~ 11000000 10101000 11111111)
1
2
3
4
5
6
7
2. 子网掩码
子网掩码(subnet mask)又叫网络掩码、地址掩码、子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码。

子网掩码不能单独存在,它必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分。
子网掩码是一个32位地址,用于屏蔽IP地址的一部分以区别网络标识和主机标识,并说明该IP地址是在局域网上,还是在远程网上。

子网掩码——屏蔽一个IP地址的网络部分的“全1”比特模式。
对于A类地址来说,默认的子网掩码是255.0.0.0;
对于B类地址来说默认的子网掩码是255.255.0.0;
对于C类地址来说默认的子网掩码是255.255.255.0。

3. 根据IP地址和子网掩码求 网络地址 和 广播地址
(1)IP地址 = 网络地址 + 主机地址(前半段和后半段)
(2)网络地址 = IP地址 & 子网掩码(按位与)
(3)主机地址 = IP地址-网络地址

通过子网掩码,就可以判断两个IP在不在一个局域网内部。网络地址相同,则说明这两个IP处于同一个局域网,友主机位区分。
子网掩码可以看出有多少位是网络号,有多少位是主机号

网络地址就是:把IP地址转成二进制和子网掩码进行与运算

主机数

主机号有5位,那么这个地址中,就只能有
2^5−2=30个主机
因为其中全0作为网络地址,全1作为广播地址

例子1:
IP地址是202.112.14.137,掩码是255.255.255.224 ,
网络地址是202.112.14.128,子网号是128。
主机地址是202.112.14.137 。

例子2:
IP地址是222.200.175.117,子网掩码是255.255.255.0。根据**C类地址的范围为192.0.0.0到223.255.255.255** ,说明这个IP属于C类地址,子网掩码采取了默认掩码。
网络地址=222.200.175.117(转换为二进制)& 255.255.255.0(转换为二进制)=222.200.175.0,子网号为0;主机地址为222.200.175.117。
处于同一个局域网中的其他机器的IP应该是222.200.175.*,例如222.200.175.2,表示主机号为2的设备;处于其他局域网的网络号应该不一样,例如222.200.174.*。
1
2
3
4
5
6
7
8
9
4. 网关
**网关(Gateway)又称网间连接器、协议转换器。**默认网关在网络层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关的结构也和路由器类似,不同的是互连层。网关既可以用于广域网互连,也可以用于局域网互连。

网关实质上是一个网络通向其他网络的IP地址。

比如有网络A和网络B,网络A的IP地址范围为“192.168.1.1~192. 168.1.254”,子网掩码为255.255.255.0;网络B的IP地址范围为“192.168.2.1~192.168.2.254”,子网掩码为255.255.255.0。这两个都是C类地址,都采用默认网关,不属于同一个网络。

在没有路由器的情况下,两个网络之间是不能进行TCP/IP通信的,即使是两个网络连接在同一台交换机(或集线器)上,TCP/IP协议也会根据子网掩码(255.255.255.0)判定两个网络中的主机处在不同的网络里。

而要实现这两个网络之间的通信,则必须通过网关。如果网络A中的主机发现数据包的目的主机不在本地网络中,就把数据包转发给它自己的网关,再由网关转发给网络B的网关,网络B的网关再转发给网络B的某个主机。

所以说,只有设置好网关的IP地址,TCP/IP协议才能实现不同网络之间的相互通信。那么这个IP地址是哪台机器的IP地址呢?网关的IP地址是具有路由功能的设备的IP地址,具有路由功能的设备有路由器、启用了路由协议的服务器(实质上相当于一台路由器)、代理服务器(也相当于一台路由器)。

5.根据每个网络的主机数量进行子网地址的规划和计算子网掩码
主机位= [ l o g 2 ( 主 机 数 量 + 1 ( 网 络 地 址 ) + 1 ( 广 播 地 址 ) + 1 ( 网 关 ) ) log_2(主机数量+1(网络地址)+1(广播地址)+1(网关))log 
2

 (主机数量+1(网络地址)+1(广播地址)+1(网关))] (向上取整)

网关用于不同网络之间的通信,必须要对其分配地址。

这也可按上述原则进行计算。

比如一个子网有10台主机,那么对于这个子网需要的IP地址是
10+1+1+1=13
注意:加的第一个1是指这个网络连接时所需的网关地址,接着的两个1分别是指网络地址和广播地址。
因为13小于16(16等于2的4次方),所以主机位为4位。

而 256-16=240 所以该子网掩码为255.255.255.240。

如果一个子网有14台主机,不少人常犯的错误是:依然分配具有16个地址空间的子网,而忘记了给网关分配地址。这样就错误了,因为:
14+1+1+1=17
17.大于16,所以我们只能分配具有32个地址(32等于2的5次方)空间的子网,留5位作主机位。256-32=224,这时子网掩码为:255.255.255.224

6. ip段/数字-如192.168.0.1/24是什么意思?
后面这个数字标示了我们的网络号的位数,也就是子网掩码中前多少号为1

(1) 129.168.1.1 /24 这个24就是告诉我们网络号是24位

也就相当于告诉我们了

子网掩码前24位为1,即:11111111 11111111 11111111 00000000

即:255.255.255.0

(2) 172.16.10.33/27 中的/27

也就是说网络号有27位,子网掩码是255.255.255.224 即前27位为1

11111111 11111111 11111111 11100000

7. 206.110.4.0/18被划分成16个子网,每个子网掩码?
(划分成16个子网,根据子网掩码/18就表示有18个1,18为网络地址,就要从的IP地址的主机位借4位来用作网络位!)

子网掩码是255.255.252.0

每个子网可以容纳的主机数是1024台。

下面我来给你详细解答:

206.110.1.0 /18 由最后的那个/18,我们可以知道这个IP已经规定了它的网络位是18位,它默认的子网掩码就是11111111.11111111.11 | 000000.00000000(其中1代表网络位,0代表主机位)

划分子网的意思是将网络号代表的某个局域网进行划分,那只能向主机位借位。

可以看出我们可以操作的位数就是后面的14个0,也就是说我们可以在主机位划分出几位作为子网的网络位,进而来划分子网。要求是切分成16个子网,我们知道2的4次方刚好等于16,这就说明子网网络位的位数是4位,那剩余的主机位,即14-4=10就是子网的主机位。
所以上面我写的那串二进制就可以变成:11111111.11111111.111111 | 00.00000000(其中1代表网络位,0代表主机位)

8. IP地址为C类的网络位,若要划分为18个子网,且都要连上Internet,子网掩码应该设置为多少?
解:C类IP地址默认以110开头,网络位为21位,主机位为8位,子网掩码默认为255.255.255.0(11111111.11111111.11111111.00000000)。
想要划分为18个子网,那么至少要向主机位借5位,则子网掩码变为11111111.11111111.11111111.11111000,转换为十进制的表示,则255.255.255.248。

9. 内网即局域网,外网即广域网
IP地址是一个4字节(共32bit)的数字,被分为4段,每段8位,段与段之间用句点分隔(句分十进制)。为了便于表达和识别,IP地址是以十进制形式表示的如210.52.207.2,每段所能表示的十进制数最大不超过255。

IP地址由两部分组成,即网络号(Network IP地址是一个4字节(共32bit)的数字,被分为4段,每段8位,段与段之间用句点分隔。为了便于表达和识别,IP地址是以十进制形式表示的如210.52.207.2,每段所能表示的十进制数最大不超过255。

IP地址由两部分组成,即网络号(Network ID)和主机号(Host ID)。
网络号标识的是Internet上的一个子网,而主机号标识的是子网中的某台主机。

网际地址分解成两个域后,带来了一个重要的优点:**IP数据包从网际上的一个网络到达另一个网络时,选择路径可以基于网络而不是主机。**不同网络之间是依赖网关进行通信。
在大型的网际中,这一点优势特别明显,因为路由表中只存储网络信息而不是主机信息,这样可以大大简化路由表。

内网就是局域网,网吧、校园网、单位办公网都属于此类。
另外光纤到楼、小区宽带、教育网、有线电视Cable
Modem上网虽然地域范围比较大但本质上还是基于以太网技术,所以仍然属于内网。

内网 vs 外网
内网:即所说的局域网(LAN),比如学校的局域网,局域网内每台计算机的IP地址在本局域网内具有互异性,是不可重复的。但两个局域网内的内网IP可以有相同的。

外网:即互联网(WAN),局域网通过一台服务器或是一个路由器对外连接的网络,这个IP地址是惟一的。

也就是说内网里所有的计算机都是连接到这一个外网IP上,通过这一个外网IP对外进行交换数据的。也就是说,一个局域网里所有电脑的内网IP是互不相同的,但共用一个外网IP。(用ipconfig/all查到的IP是你本机的内网IP;在www.ip138.com上看到的是你连接互联网所使用的IP,即外网)。

在局域网中,每台电脑都可以自己分配自己的IP,这个IP只在局域网中有效。而如果你将电脑连接到互联网,你的网络提供商(ISP)的服务器会为你分配一个IP地址,这个IP地址才是你在外网的IP。两个IP同时存在,一个对内,一个对外。
当你家里买了两台电脑,你想组建一个局域网,你除了要用网线和路由器等设备将两台电脑相连,你还要将两台电脑设置固定IP(局域网IP),比如电脑A设为192.168.1.2,电脑B设为192.168.1.3,这样你就可以用这两个IP地址互相访问两台电脑,但这两个IP地址只在这两台电脑间有效,对外网无效。所以局域网中分配的IP与广域网中的IP完全没有对应关系。你在内网的机子在上网时,都是在向网关发出请求,再由网关(一般为路由器)用外网IP转到Internet上,接收数据后,再分发到你的内网IP上。
————————————————
版权声明:本文为CSDN博主「Chaser_LittleBee」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sinat_21591675/article/details/82844611
用pip管理工具安装库文件时,默认使用国外的源文件,因此在国内的下载速度会比较慢,可能只有50KB/s。幸好,国内的一些顶级科研机构已经给我们准备好了各种镜像,下载速度可达2MB/s。
其中,比较常用的国内镜像包括:

(1)阿里云 http://mirrors.aliyun.com/pypi/simple/
(2)豆瓣http://pypi.douban.com/simple/
(3)清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
(4)中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
(5)华中科技大学http://pypi.hustunique.com/

注意:新版ubuntu要求使用https源。

设置方法:(以清华镜像为例,其它镜像同理)
(1)临时使用:
可以在使用pip的时候,加上参数-i和镜像地址(如
https://pypi.tuna.tsinghua.edu.cn/simple),
例如:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pandas,这样就会从清华镜像安装pandas库。

(2)永久修改,一劳永逸:
(a)Linux下,修改 ~/.pip/pip.conf (没有就创建一个文件夹及文件。文件夹要加“.”,表示是隐藏文件夹)
内容如下:

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host = https://pypi.tuna.tsinghua.edu.cn

(b) windows下,直接在user目录中创建一个pip目录,如:C:\Users\xx\pip,然后新建文件pip.ini,即 %HOMEPATH%\pip\pip.ini,在pip.ini文件中输入以下内容(以豆瓣镜像为例):

[global]
index-url = http://pypi.douban.com/simple
[install]
trusted-host = pypi.douban.com

创建pip.ini文件可以用文本编辑器,例如 sublime text3。

引言: Tensorflow大名鼎鼎,这里不再赘述其为何物。这里讲描述在安装python包的时候碰到的“No matching distribution found for tensorflow”,其原因以及如何解决。

简单的安装tensorflow
这里安装的tensorflow的cpu版本,gpu版本可以自行搜索安装指南,或者参考如下指令:

pip3 install tensorflow #cpu

这里使用的python 3.6.3版本。

pip3 install tensorflow-gpu

这里是gpu的版本。

window的环境
window 7.

问题描述:
pip3 install tensorflow

如此简单的指令,应该不会出错吧,结果得到如下错误信息:

Collecting tensorflow
Could not find a version that satisfies the requirement tensorflow (from versions: ) No matching distribution found for tensorflow

为什么没有找到tensorflow呢?那我们自行找找看吧?

pip3 search tensorflow

具体的输出信息如下:

…………………..
tensorbase (0.3) - Minimalistic TensorFlow
Framework
tensorbayes (0.3.0) - Deep Variational Inference in
TensorFlow
tensorflow-tensorboard (0.4.0rc3) - TensorBoard lets you watch
Tensors Flow
tensorboard_logger (0.0.4) - Log TensorBoard events without
Tensorflow
tensorboardX (0.8) - TensorBoardX lets you watch
Tensors Flow without Tensorflow
tensorbuilder (0.3.6) - A light wrapper over TensorFlow
that enables you to easily
create complex deep neural
networks using the Builder
Pattern through a functional
fluent immutable API
tensorflow-utils (0.1.0) - Classes and methods to make
using TensorFlow easier
tensorflow-transform (0.4.0) - A library for data
preprocessing with TensorFlow
tensorflow (1.5.0rc0) - TensorFlow helps the tensors
flow
tensorflow_forward_ad (0.3.3) - TensorFlow forward-mode
automatic differentiation
tensorflow_hmm (0.4.1) - Tensorflow and numpy
implementations of the HMM
viterbi and forward/backward
algorithms
tensorflow_nlp (0.0.1) - Deep Learning NLP Tasks
implemented on Tensorflow
tensorflowonspark (1.1.0) - Deep learning with TensorFlow
on Apache Spark clusters
tensorflowservingclient (0.5.1.post2) - Prebuilt tensorflow serving
client
tensorforce (0.3.4) - Reinforcement learning for
TensorFlow
tensorfunk (0.0.0) - tensorflow model converter to
create tensorflow-independent
prediction functions.
tensorfuse (0.0.1) - Common interface for Theano,
CGT, and TensorFlow
tensorgraph (3.5.8) - A high level tensorflow library
for building deep learning
models
tensorhive (0.1.1) - Lightweight computing resource
management tool for executing
distributed TensorFlow programs
tensorlm (0.3) - TensorFlow wrapper for deep
neural text generation on
character or word level with
RNNs / LSTMs
TensorMol (0.1) - TensorFlow+Molecules =
TensorMol
tensorpack (0.8.0) - Neural Network Toolbox on
TensorFlow
tensorpy (1.1.0) - Easy Image Classification with
TensorFlow!
tensorrec (0.1) - A TensorFlow recommendation
algorithm and framework in
Python.
tensorspark (1.0.6) - Tensorflow on Spark, a scalable
system for high-performance
machine learning
tensorvision (0.1.dev1) - A library to build and train
neural networks in with
TensorFlow for Computer Vision
TFANN (1.0.1) - A neural network module
containing implementations of
MLP, and CNN networks in
TensorFlow.
TFBOYS (0.0.1) - TensorFlow BOYS
tfcf (0.0.0) - A tensorflow-based recommender
system.
tfcoreml (0.1.0) - Tensorflow to Core ML converter
tfdebugger (0.1.1) - TensorFlow Debugger
tfdeploy (0.4.2) - Deploy tensorflow graphs for
fast evaluation and export to
tensorflow-less environments
running numpy.
tfgraph (0.2) - Python’s Tensorflow Graph
Library
tfgraphviz (0.0.6) - A visualization tool to show a
graph like TensorFlow and
TensorBoard
…………………………………………

悲伤的我如此难以自抑,明明可以找到的,怎么却无法安装嗯?我需要自行好好找找明明是谁? :-)

问题分析
二话不说,直接上官网上查查看,虽然官网离我朝远隔万里,需要跋山涉水之后方可达到。翻过拿到看不见的墙之后,重要可以看到官方信息了。
官方路标如下: https://www.tensorflow.org/install/install_windows
其中所提安装步骤非常简洁,如此简洁的步骤,怎么可能出错? 于是重新梳理了一下,难道是Python或者pip3本身的问题吗?

check pip3

pip –version

发现其为最新版本:

pip 9.0.1 from d:\program files (x86)\python\lib\site-packages (python 3.6)

那Python呢? 官方文档中提到如下:

If one of the following versions of Python is not installed on your machine, install it now:
* Python 3.5.x 64-bit from python.org
* Python 3.6.x 64-bit from python.org

难道我安装的python是假python不成? 估计有可能吧,难道是64bit的问题?

检查python的版本
python -v

得到了python的完整信息:

..........................................
> D:\Program Files (x86)\python\lib\__pycache__\sysconfig.cpython-36.pyc matches D:\Program Files (x86)\python\lib\sysconfig.py
>  code object from 'D:\\Program Files (x86)\\python\\lib\\__pycache__\\sysconfig.cpython-36.pyc'
import 'sysconfig' # <_frozen_importlib_external.SourceFileLoader object at 0x006A1230>
> D:\Program Files (x86)\python\lib\__pycache__\_bootlocale.cpython-36.pyc matches D:\Program Files (x86)\python\lib\_bootlocale.py
> code object from 'D:\\Program Files (x86)\\python\\lib\\__pycache__\\_bootlocale.cpython-36.pyc'
import '_locale' # <class '_frozen_importlib.BuiltinImporter'>
import '_bootlocale' # <_frozen_importlib_external.SourceFileLoader object at 0x007911D0>
> D:\Program Files (x86)\python\lib\encodings\__pycache__\gbk.cpython-36.pyc matches D:\Program Files (x86)\python\lib\encodings\gbk.py
> code object from 'D:\\Program Files (x86)\\python\\lib\\encodings\\__pycache__\\gbk.cpython-36.pyc'
import '_codecs_cn' # <class '_frozen_importlib.BuiltinImporter'>
import '_multibytecodec' # <class '_frozen_importlib.BuiltinImporter'>
import 'encodings.gbk' # <_frozen_importlib_external.SourceFileLoader object at 0x00791490>
import 'site' # <_frozen_importlib_external.SourceFileLoader object at 0x004F73D0>
Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
import 'atexit' # <class '_frozen_importlib.BuiltinImporter'>

其中关于python的关键信息:

Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)] on win32

“32bit” !!! 一口老血喷出,众里寻他千百度,蓦然回首bug正在这灯火阑珊处。原来是python版本的问题导致的。

修复问题
重新下载一个64bit的python版本,之后重新操作就可以了。

python -v

查看其中的关键信息:

Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)] on win32

确认是64位,没有问题。

然后直接安装tensorflow:

pip3 install tensorflow

安装过程如下:

C:\windows\system32>pip3 install tensorflow
Collecting tensorflow
  Downloading tensorflow-1.4.0-cp36-cp36m-win_amd64.whl (28.3MB)
    100% |████████████████████████████████| 28.3MB 39kB/s
Collecting enum34>=1.1.6 (from tensorflow)
  Downloading enum34-1.1.6-py3-none-any.whl
Requirement already satisfied: wheel>=0.26 in d:\program files (x86)\python\lib\site-packages (from tensorflow)
Collecting protobuf>=3.3.0 (from tensorflow)
  Downloading protobuf-3.5.1-py2.py3-none-any.whl (388kB)
    100% |████████████████████████████████| 389kB 593kB/s
Collecting tensorflow-tensorboard<0.5.0,>=0.4.0rc1 (from tensorflow)
  Downloading tensorflow_tensorboard-0.4.0rc3-py3-none-any.whl (1.7MB)
    100% |████████████████████████████████| 1.7MB 182kB/s
Requirement already satisfied: six>=1.10.0 in d:\program files (x86)\python\lib\site-packages (from tensorflow)
Collecting numpy>=1.12.1 (from tensorflow)
  Downloading numpy-1.13.3-cp36-none-win_amd64.whl (13.1MB)
    100% |████████████████████████████████| 13.1MB 81kB/s
Requirement already satisfied: setuptools in d:\program files (x86)\python\lib\site-packages (from protobuf>=3.3.0->tensorflow)
Collecting html5lib==0.9999999 (from tensorflow-tensorboard<0.5.0,>=0.4.0rc1->tensorflow)
  Downloading html5lib-0.9999999.tar.gz (889kB)
    100% |████████████████████████████████| 890kB 504kB/s
Collecting bleach==1.5.0 (from tensorflow-tensorboard<0.5.0,>=0.4.0rc1->tensorflow)
  Downloading bleach-1.5.0-py2.py3-none-any.whl
Requirement already satisfied: werkzeug>=0.11.10 in d:\program files (x86)\python\lib\site-packages (from tensorflow-tensorboard<0.5.0,>=0.4.0rc1->tensorflow)
Collecting markdown>=2.6.8 (from tensorflow-tensorboard<0.5.0,>=0.4.0rc1->tensorflow)
  Downloading Markdown-2.6.11-py2.py3-none-any.whl (78kB)
    100% |████████████████████████████████| 81kB 583kB/s
Building wheels for collected packages: html5lib
  Running setup.py bdist_wheel for html5lib ... done
  Stored in directory: C:\Users\chenjunfeng1\AppData\Local\pip\Cache\wheels\6f\85\6c\56b8e1292c6214c4eb73b9dda50f53e8e977bf65989373c962
Successfully built html5lib
Installing collected packages: enum34, protobuf, html5lib, numpy, bleach, markdown, tensorflow-tensorboard, tensorflow
Successfully installed bleach-1.5.0 enum34-1.1.6 html5lib-0.9999999 markdown-2.6.11 numpy-1.13.3 protobuf-3.5.1 tensorflow-1.4.0 tensorflow-tensorboard-0.4.0rc3

存储类(Storage Classes)
如前文所述,SQLite在处理数据类型时与其它的数据库不同。区别在于它所支持的类型以及这些类型是如何存储、比较、强化(enforc)和指派(assign)。下面各节介绍SQLite处理数据类型的独特方法和它与域完整性的关系。

对于数据类型,SQLite的域完整性被称为域亲和性(affinity)更合适。在SQLite中,它被称为类型亲和性(type affinity)。为了理解类型亲和性,你必须先要理解存储类和弱类型(manifesttyping)。

SQLite有5个原始的数据类型,被称为存储类。存储类这个词表明了一个值在磁盘上存储的格式,其实就是类型或数据类型的同义词。这5个存储类在表4-6中描述。

表 4-6 SQLite存储类

                       

 


   
说明
INTEGER
整数值是全数字(包括正和负)。整数可以是1, 2, 3, 4, 6或 8字节。整数的最大范围(8 bytes)是{-9223372036854775808, 0, +9223372036854775807}。SQLite根据数字的值自动控制整数所占的字节数。
空注:参可变长整数的概念。

REAL
实数是10进制的数值。SQLite使用8字节的符点数来存储实数。

 
TEXT
文本(TEXT)是字符数据。SQLite支持几种字符编码,包括UTF-8和UTF-16。字符串的大小没有限制。

 
 
BLOB
二进制大对象(BLOB)是任意类型的数据。BLOB的大小没有限制。

 
 

NULL

NULL表示没有值。SQLite具有对NULL的完全支持。


 
SQLite通过值的表示法来判断其类型,下面就是SQLite的推理方法:

l  SQL语句中用单引号或双引号括起来的文字被指派为TEXT。

l  如果文字是未用引号括起来的数据,并且没有小数点和指数,被指派为INTEGER。

l  如果文字是未用引号括起来的数据,并且带有小数点或指数,被指派为REAL。

l  用NULL说明的值被指派为NULL存储类。

l  如果一个值的格式为X'ABCD',其中ABCD为16进制数字,则该值被指派为BLOB。X前缀大小写皆可。

SQL函数typeof()根据值的表示法返回其存储类。使用这个函数,下面SQL语句返回的结果为:

sqlite> select typeof(3.14),typeof('3.14'), typeof(314), typeof(x'3142'), typeof(NULL);

typeof(3.14)   typeof('3.14')  typeof(314)    typeof(x'3142')       typeof(NULL)

real                text                integer           blob                      null

 

SQLite单独的一个字段可能包含不同存储类的值。请看下面的示例:

sqlite> DROP TABLE domain;

sqlite> CREATE TABLE domain(x);

sqlite> INSERT INTO domain VALUES(3.142);

sqlite> INSERT INTO domain VALUES('3.142');

sqlite> INSERT INTO domain VALUES(3142);

sqlite> INSERT INTO domain VALUES(x'3142');

sqlite> INSERT INTO domain VALUES(NULL);

sqlite> SELECT ROWID, x, typeof(x) FROMdomain;

返回结果为:

rowid      x            typeof(x)

1            3.142      real

2            3.142      text

3            3142     integer

4            1B        blob

5            NULL    null

这带来一些问题。这种字段中的值如何存储和比较?如何对一个包含了INTEGER、REAL、TEXT、BLOB和NULL值的字段排序?一个整数和一个BLOB如何比较?哪个更大?它们能相等吗?

答案是:具有不同存储类的值可以存储在同一个字段中。可以被排序,因为这些值可以相互比较。有完善定义的规则来做这件事。不同存储类的值可以通过它们各自类的“类值”进行排序,定义如下:

1. NULL存储类具有最低的类值。一个具有NULL存储类的值比所有其它值都小(包括其它具有NULL存储类的值)。在NULL值之间,没有特别的可排序值。

2. INTEGER或REAL存储类值高于NULL,它们的类值相等。INTEGER值和REAL值通过其数值进行比较。

3. TEXT存储类的值比INTEGER和REAL高。数值永远比字符串的值低。当两个TEXT值进行比较时,其值大小由“排序法”决定。

4. BLOB存储类具有最高的类值。具有BLOB类的值大于其它所有类的值。BLOB值之间在比较时使用C函数memcmp()。

所以,当SQLite对一个字段进行排序时,首先按存储类排序,然后再进行类内的排序 (NULL类内部各值不必排序) 。下面的SQL说明了存储类值的不同:

sqlite> SELECT 3 < 3.142, 3.142 <'3.142', '3.142' < x'3000', x'3000' < x'3001';

返回:

3 < 3.142              3.142 < '3.142'              '3.142'< x'3000'     x'3000' < x'3001'

1                   1                          1                          1

 

弱类型(manifest typing)
SQLite使用弱类型。

看下面的表:

CREATE TABLE foo( x integer,

    y text, z real );

向该表插入一条记录:

INSERT INTO foo VALUES ('1', '1', '1');

当SQLite创建这条记录时,x、y和z这3个字段中存储的是什么类型呢?答案是INTEGER, TEXT和REAL。

 

再看下面例子:

CREATE TABLE foo(x, y, z);

现在执行同样的插入语句:

INSERT INTO foo VALUES ('1', '1', '1');

现在,x、y和z中存储的是什么类型呢?答案是TEXT、TEXT和TEXT。

那么,是否SQLite的字段类型默认为TEXT呢?再看,还是第2个表,执行如下插入语句:

INSERT INTO foo VALUES (1, 1.0, x'10');

现在,x、y和z中存储的是什么类型呢?答案是INTEGER、REAL和BLOB。

 

如果你愿意,可以为SQLite的字段定义类型,这看起来跟其它数据库一样。但这不是必须的,你可以尽管违反类型定义。这是因为在任何情况下,SQLite都可以接受一个值并推断它的类型。

总之,SQLite的弱类型可表示为:1)字段可以有类型,2)类型可以通过值来推断。类型亲和性介绍这两个规定如何相互关联。所谓类型亲和性就是在强类型(strict typing)和动态类型(dynamic typing)之间的平衡艺术。

类型亲和性(Type Affinity)
在SQLite中,字段没有类型或域。当给一个字段声明了类型,该字段实际上仅仅具有了该类型的新和性。声明类型和类型亲和性是两回事。类型亲和性预定 SQLite用什么存储类在字段中存储值。在存储一个给定的值时到底SQLite会在该字段中用什么存储类决定于值的存储类和字段亲和性的结合。我们先来介绍一下字段如何获得它的亲和性。

字段类型和亲和性
首先,每个字段都具有一种亲和性。共有四种亲和性:NUMERIC、INTEGER、TEXT和NONE。一个字段的亲和性由它预声明的类型决定。所以,当你为字段声明了类型,从根本上说是为字段指定了亲和性。SQLite按下面的规则为字段指派亲和性:

l  默认的,一个字段默认的亲和性是NUMERIC。如果一个字段不是INTEGER、TEXT或NONE的,那它自动地被指派为NUMERIC亲和性。

l  如果为字段声明的类型中包含了'INT'(无论大小写),该字段被指派为INTEGER亲和性。

l  如果为字段声明的类型中包含了'CHAR'、'CLOB'或'TEXT'(无论大小写),该字段被指派为TEXT亲和性。如'VARCHAR'包含了'CHAR',所以被指派为TEXT亲和性。

l  如果为字段声明的类型中包含了'BLOB'(无论大小写),或者没有为该字段声明类型,该字段被指派为NONE亲和性。

注意:如果没有为字段声明类型,该字段的亲和性为NONE,在这种情况下,所有的值都将以它们本身的(或从它们的表示法中推断的)存储类存储。如果你暂时还不确定要往一个字段里放什么内容,或准备将来修改,用NONE亲和性是一个好的选择。但SQLite默认的亲和性是NUMERIC。例如,如果为一定字段声明了类型JUJYFRUIT,该字段的亲和性不是NONE,因为SQLite不认识这种类型,会给它指派默认的NUMERIC亲和性。所以,与其用一个不认识的类型最终得到NUMERIC亲和性,还不如不为它指定类型,从而使它得到NONE亲和性。

亲和性和存储
亲和性对值如何存储到字段有影响,规则如下:

l  一个NUMERIC字段可能包括所有5种存储类。一个NUMERIC字段具有数字存储类的偏好(INTEGER和REAL)。当一个TEXT值被插入到一个NUMERIC字段,将会试图将其转化为INTEGER存储类;如果转化失败,将会试图将其转化为REAL存储类;如果还是失败,将会用TEXT存储类来存储。

l  一个INTEGER字段的处理很像NUMERIC字段。一个INTEGER字段会将REAL值按REAL存储类存储。也就是说,如果这个REAL值没有小数部分,就会被转化为INTEGER存储类。INTEGER字段将会试着将TEXT值按REAL存储;如果转化失败,将会试图将其转化为INTEGER存储类;如果还是失败,将会用TEXT存储类来存储。

l  一个TEXT字段将会把所有的INTEGER或REAL值转化为TEXT。

l  一个NONE字段不试图做任何类型转化。所有值按它们本身的存储类存储。

l  没有字段试图向NULL或BLOB值转化——如无论用什么亲和性。NULL和BLOB值永远都按本来的方式存储在所有字段。

这些规则初看起来比较复杂,但总的设计目标很简单,就是:如果你需要,SQLite会尽量模仿其它的关系型数据库。也就是说,如果你将SQLite看成是一个传统数据库,类型亲和性将会按你的期望来存储值。如果你声明了一个INTEGER字段,并向里面放一个整数,就会按整数来存储。如果你声明了一个具有 TEXT, CHAR或VARCHAR类型的字段并向里放一个整数,整数将会转化为TEXT。可是,如果你不遵守这些规定,SQLite也会找到办法来存储你的值。

亲和性的运行
让我们看一些例子来了解亲和性是如何工作的:

sqlite> CREATE TABLE domain(i int, nnumeric, t text, b blob);

sqlite> INSERT INTO domain VALUES(3.142,3.142,3.142,3.142);

sqlite> INSERT INTO domain VALUES('3.142','3.142','3.142','3.142');

sqlite> INSERT INTO domain VALUES(3142,3142,3142,3142);

sqlite> INSERT INTO domain VALUES(x'3142',x'3142',x'3142',x'3142');

sqlite> INSERT INTO domain VALUES(null,null,null,null);

sqlite> SELECT ROWID,typeof(i),typeof(n),typeof(t),typeof(b)FROM domain;

返回:

rowid      typeof(i)  typeof(n) typeof(t)  typeof(b)

1            real         real         text         real

2            real         real         text         text

3            integer    integer    text         integer

4            blob        blob        blob        blob

5            null         null         null         null

下面的SQL说明存储类的排序情况:

sqlite> SELECT ROWID, b, typeof(b) FROMdomain ORDER BY b;

返回:

rowid b typeof(b)

5 NULL null

1 3.142 real

3 3142 integer

2 3.142 text

4 1B blob

sqlite> SELECT ROWID, b, typeof(b),b<1000 FROM domain ORDER BY b;

返回:

rowid b typeof(b) b<1000

NULL null NULL

1 3.142 real 1

3 3142 integer 1

2 3.142 text 0

4 1B blob 0

存储类和类型转换
关于存储类,需要关注的另一件事是:存储类有时会影响到值如何进行比较。特别是SQLite有时在进行比较之前,会将值在数字存储类(INTEGER和REAL)和TEXT之间进行转换。为进行二进制的比较,遵循如下规则:

l  当一个字段值与一个表达式的结果进行比较,字段的亲和性会在比较之前应用于表达式的结果。

l  当两个字段值进行比较,如果一个字段拥有INTEGER或NUMERIC亲和性而另一个没有,NUMERIC亲和性会应用于非NUMERIC字段的TEXT值。

l  当两个表达式进行比较,SQLite不做任何转换。如果两个表达式有相似的存储类,则直接按它们的值进行比较;否则按类值进行比较。

请看下面例子:

sqlite> selectROWID,b,typeof(i),i>'2.9' from domain ORDER BY b;

rowid b typeof(i i>'2.9'

5 NULL null NULL

1 3.142 real 1

3 3142 integer 1

2 3.142 real 1

4 1B blob 1

也算是“强类型(STRICT TYPING)”
如果你需要比类型亲和性更强的域完整性,可以使用CHECK约束。你可以使用一个单独的内置函数和一个CHECK约束来实现一个“假的”强类型。
下一页
上一页
回到顶部
Powered by 顾羽宸. Written by . 浙icp备87656888号
在路上...     27.89ms