SQL学习记录
之前有简单弄过表设计,也做过存储过程,但是都是野战出身,经常被卡到一些问题上,只能上网寻找答案,终于有时间来真正学习整理正规知识了,在此记录核心难点重点,以备复习。(大学,什么都没学到,今天,一天看完,一天实践测试,一天记录,以后再回头看看,就解决了。游戏的大学……)
1:在SQL中,若使用索引,则相当于建立了一个加了桶的红黑树。查询速度极快,无需遍历。若不建立索引,SQL并无太多优势。 2:若没有建立索引,则SQL数据并没有所谓的顺序性,即“查找前10个数据”这样的概念在SQL内是不存在的。 3:SQL内的master, model, msdb, tempdb 等系统库请不要进行修改。
一:查找关键字 不再详细记录:为记住关键字,保存几句语法( SQL语句大小写不敏感 )
SELECT ResultParagraph FROM table WHERE ConditionParagraph = 'WhatWeWant'
SELECT ResultParagraph FROM table WHERE ConditionParagraph = 'WhatWeWant1' OR ConditionParagraph = 'WhatWeWant2'
SELECT ResultParagraph FROM table WHERE ConditionParagraph1 = 'WhatWeWant1' AND ConditionParagraph2 = 'WhatWeWant2'
SELECT ResultParagraph FROM table WHERE ConditionParagraph = 'WhatWeWant' NOT ConditionParagraph = 'WhatWeDonNotWant'
SELECT ResultParagraph1,ResultParagraph2 FROM table WHERE ConditionParagraph = 'WhatWeWant'
SELECT * FROM table
多表,无关联,组合结果
SELECT ResultParagraph1, ResultParagraph2 FROM table1, table2
多表,建立关联,非组合结果
SELECT ResultParagraph1, ResultParagraph2 FROM table1, table2 WHERE table1.ConditionParagraph1 = table2.ConditionParagraph1 AND table1.ConditionParagraph2 = table2.ConditionParagraph2
1:若两个表内为1对1,或者1对多的关系时,可在两个表内增加一个相同字段进行对应关系;当两个表内有“多对多”的关系时,尽量建立第三方表来实现对应关系。
SELECT ResultParagraph "RenameParagrah" FROM table --- 修改段名输出
SELECT ResultParagraph "Paragrah",ResultParagraph*2 "NewParagrah" FROM table WHERE ConditionParagraph = 'WhatWeWant'
SELECT ResultParagraph1*ResultParagraph2 "NewParagrah" FROM table WHERE ConditionParagraph = 'WhatWeWant'
SELECT ResultParagraphFirstName + " " + ResultParagraphSecondName "TotalName" FROM table WHERE ConditionParagraph = 'WhatWeWant'
二:排序关键字
SELECT * FROM table ORDER BY ConditionParagraph -- 顺排序
SELECT * FROM table ORDER BY ConditionParagraph1,ConditionParagraph2 -- 多条件顺排序
SELECT * FROM table ORDER BY ConditionParagraph DESC -- 逆排序
1:不是特别需要时,不要对查询结果排序,这将花费更多时间。当然,比编程语言中排序还是快。若建立了索引,则将更快。
重复互斥关键字
SELECT DISTINCT ResultParagraph FROM table WHERE ConditionParagraph = ‘WhatWeWant’ –去除重复结果
1:和OrderBy一样,去除重复值会带来额外开销。
三:创建表关键字
CREATE TABLE newTable( Paragraph1 VARCHAR(100), Paragraph2 TEXT, Paragraph3 DATATIME )
SQL数据类型 VARCHAR 字符型,有传闻说该数据最多支持255字节,但经测试SQLServer2000和2005都是支持最大为8000字节,2005中还有个特别的支持无限大的VARCHAR类型。个人理解这个类型是个指针存储。例子中
100为指定字段长度为100,当填充的字节数超过100.则直接截断保存。 TEXT 文本型,为VARCHAR加强版,可以存储极大的字符类型。 INT 整数型,和C++中32位的signed int范围一样。 SAMLLINT 短整型,和C++中32位signed short范围一样。 TINYINT 和C++中unsigned char范围一样。 NUMERIC 它占9个字节,可表示-10的38次方到10的38次方内的数,并可表示小数,不过定义时,需要指定整数部分和小数部分的大小长度。例如 CREATE TABLE newTable( Paragraph NUMERIC(13, 12 )) SMALLMONEY 它可以存储从 -214748.3648 到 214748.3647 的数。但就个人看来,实际保存的应当还是int,仅仅是将最后的值除以10000返回给我们了而已。 MONEY 它可以存储 -2的63次方除以10000 至 2的63次方除以10000 之内的值,怎么看都是 int64 保存,最后将值除以10000返回给我们。 BIT 只能保存0或1. DATETIME 时间类型,8字节,它可以记录1753年1月1日到9999年12月31日之间的 毫秒级 的时间。 SAMLLDATETIME 4字节,它可以记录1900年1月1日至2079年6月6日之间的 秒 级的时间。 CHAR 字符型,在2005下它最大和VARCHAR一样,最大支持8000字节。
1:避免使用TEXT,一旦向TEXT文本型中输入任何数据(包括空值),就会直接分配2K空间给该数据,除非我们删除该记录行,否则将无法回收这部分空间。TEXT不仅占用磁盘存储空间大,还很慢。 2:NUMERIC的整数部分长度最大28位,其小数部分必须小于整数部分位数,小数部分允许位数为0。 3:有些书上说BIT类型字段必须在建表时才可创建,在表创建完毕后,无法向表中添加BIT字段,但我在SQLServer2005中又确实可以在表创建后再添加BIT字段,很是奇怪。 4:除非特殊需要,我们尽量使用SAMLLDATETIME类型,这远比我们使用 SMALLINT记录年份TINYINT记录月份TINYINT记录日期 便捷得多,DATETIME结构有API函数可以转成我们可以容易理解的结构。且有
GetDate这样函数更便捷的获取该结构的时间。 5:VARCHAR 和 CHAR 区别如下:假设我们有一个100字节的VARCHAR字段,一个100字节CHAR字段,分别填入一份40字节的数据。那么之后从VARCHAR中取得该字段数据时,会获得一个40字节的字符。而从
CHAR中取得该字段数据时,会获得一个100字节的字符,后面60位会自动被填充0。这样我们可以看出VARCHAR不仅简便了我们的使用(不用去清0)而且,占用的空间也比CHAR小,无特殊原因,尽量使用
VARCHAR的好。
CREATE TABLE newTable( C1 CHAR(200) NOT NULL ) – 禁止空值 CREATE TABLE newTable( Paragraph1 CHAR(200) NULL, Paragraph2 VARCHAR(120) DEFAULT ‘Hello’, Paragraph1 DATETIME DEFAULT GETDATE() ) – 缺省值 CREATE TABLE newTable( Paragraph1 INT IDENTITY ) – 标识字段
1:空值不是0. 2:BIT类型绝对不可能是空值,它只允许是0或者1 3:标识字段是全表唯一的,但它不是主键。它的特点是,必须是INT,SMALLINT,TINYINT,NUMERIC这些数字类型。它的特点是,每插入一条新数据时,该字段内数据会自动根据我们指定的标识递增量自
动递增并填充表内。 4:注意,表内的表示字段不能保证其连续性。且,被设置为标识字段的数据,不允许手动insert插入自定义数据。 5:GETDATE()是SQL函数,可以获得当前日期和时间。我们可以在之后使用CONVERT转换该时间格式。
四:删除、修改表关键字
DROP TABLE tableName – 删除表 TRUNCATE TABLE tableName – 清空表内数据(保留表字段) ALTER TABLE tableName ADD Paragraph INT NULL – 对一个已有的表添加新字段
1:DROP TABLE后,该表将无法恢复,谨慎使用。 2:ADD添加字段,该字段必须允许为NULL,因为之前可能已有许多数据。
五:索引
索引的实现原理,2叉树。 聚簇索引的2叉查找树每个叶内直接存放有数据信息内容。 非聚簇索引的2叉查找树每个叶内存放的是指针,指向数据所存放的物理位置。 可以指定某索引字段为唯一索引,唯一索引的概念是,该字段内的所有数据不可相同。聚簇索引以及非聚簇索引均可指定为唯一索引。
1:索引目的是加速查找速度,但很消耗空间,并且在插入以及更新数据的时候也会减缓速度。索引越多,占用空间越大,插入越慢。创建一个聚簇索引,相当于增加了0.2倍原数据的空间大小, 2:由于聚簇索引保存的是数据物理地址,数据物理地址存放方式只能有一套,所以在一个表内它是唯一的;而非聚簇索引仅仅保存指针,所以在一个表内允许有多个非聚簇索引。 3:聚簇索引的主键比非聚簇索引的主键插入速度慢很多。但SQL默认在设置主键时会自动将该字段设置为聚簇索引。 4:聚簇索引,标识字段,主键是三个不同概念,但,在一个表内,这三个定义都具有唯一性。 5:聚簇索引,允许是各种类型字段。 6:通常来说,聚簇索引的数据访问比非聚簇索引的数据访问要快。 7:聚簇索引是唯一的,非聚簇索引在一个表内最多可以拥有249个,但是,非聚簇索引依旧占用硬盘和内存空间,插入/更新速度依旧会影响,所以,尽量减少简历索引条目,通常一个表不要超8个为佳
。 8:允许对多个字段创建一个复合索引。该索引允许唯一非唯一,允许聚簇非聚簇。
CREARE INDEX newIndex ON tableName( Paragraph ) – 在Paragraph字段创建一个newIndex的非聚簇,非唯一索引。(非聚簇非唯一是索引默认属性) DROP INDEX tableName.newIndex – 删除一个索引 CREARE CLUSTERED INDEX newIndex ON tableName( Paragraph ) – 创建一个聚簇索引 CREARE UNIQUE CLUSTERED INDEX newIndex ON tableName( Paragraph ) – 创建一个唯一聚簇索引 CREARE INDEX newIndex ON tableName( Paragraph1, Paragraph2 ) – 为两个字段创建一个复合索引(非唯一,非聚簇)
六:插入语句
INSERT newTable( Paragraph ) VALUES( ‘TestValue’ ) INSERT newTable( Paragraph1,Paragraph2 ) VALUES( ‘TestValue1’, ‘TestValue2’ )
1:对文本型(TEXT)插入较长信息时,建议是WRITETEXT而避免使用INSERT 2:若你未对一个字段赋值,它将会使用其标识值,若非标识字段,则会使用缺省值,若无缺省值且允许空值,则会插入空值,若既非标志字段,有无缺省值,且不许空值,则会报错。 3:@@identity 可以记录上一变量值。例如: INSERT newTable( Paragraph ) VALUES( ‘TestValue’ ) – 此句执行之后 @@identity将表示‘TestValue’ INSERT newTable2( Paragraph ) VALUES ( @@identity ) – 将’TestValue’同样填充到新表2的字段内
七:删除语句
DELETE newTable WHERE Paragraph=‘WhatWeWant’
1:条件内同样可使用 OR,AND,NOT 2:DELETE newTable 后不加任何条件的话,可以删除一个表,但是这样效率比较低,DELETE操作是会记录删除操作的。而若想清表,可以使用 TRUNCATE newTable来清除,这个操作不做记录,会块的多
。
八:更新语句
UPDATE newTable SET Paragraph=‘WhatWeWant’WHERE Paragraph=‘WhatWeNeed’
1:对文本型字段可使用UPDATE语句,但大段的文本数据建议使用UPDATETEXT语句更迅速。
九:拷贝记录
INSERT newTable( Paragraph1, Paragraph2 ) SELECT Paragraph3, Paragraph4 FROM srcTable WHERE Paragraph3 = ‘WhatWeWant’ SELECT * INTO newTable FROM srcTable SELECT Paragraph1 INTO newTable FROM srcTable WHERE Paragraph3 = ‘WhatWeWant’
1:我们在删除一个表的时候,有理由先将其中部分信息进行备份处理,那么我们需要进行拷贝。 2:SQL中进行字段的删除并不方便,或者对一个字段的数据类型进行修改也并不方便,此时我们可以使用上面的拷贝方式。
十:统计语句
SELECT COUNT( Paragraph1 ) FROM tableName – 不排除重复的 SELECT COUNT( DISTINCT Paragraph1 ) FROM tableName WHERE Paragraph3 = ‘WhatWeWant’ – 取得复合条件的个数,且排除了重复的结果,重复的算为1 SELECT AVG( Paragraph1 ) FROM Paragraph – 求平均值 SELECT SUM( Paragraph1 )‘TotalSum’ FROM Paragraph – 求和,并将返回值字段显示修改 SELECT MAX( Paragraph1 ) FROM Paragraph – 求最大值 SELECT MIN( Paragraph1 ) FROM Paragraph – 求最小值
1:注意,COUNT时,空值会被自动排除掉。 2:若希望得到记录内的条数,而不管是否空值的话,可以使用下语句 SELECT COUNT(*) FROM tableName 3:AVG以及SUM函数只可对数字型以及MOENY型字段使用。 4:求最小值MIN中,空值比所有值都小。
十一:范围语句
SELECT Paragraph FROM tableName WHERE Paragraph2 > 6 AND Paragraph2 < 10 SELECT Paragraph FROM tableName WHERE Paragraph2 BETWEEN 6 AND 10 – 等价上一句
SELECT Paragraph FROM tableName WHERE Paragraph2 = 1 OR Paragraph2 = 10 SELECT Paragraph FROM tableName WHERE Paragraph2 IN (1, 10) – 等价上一句,注意,括号内数据并不代表一个范围,而是具体的值的枚举
SELECT Paragraph FROM tableName WHERE Paragraph2 NOT BETWEEN 6 AND 10 – 取出非6-10内的数据
十二:转换语句
SELECT CONVERT( CHAR(16), Paragraph ) + ‘YuanRMB’ FROM tableName – 将 Paragraph字段转换为 CHAR类型。并且将原类型后加字符串再填入
1:CONVERT还可以将DATE类型转换为不同的格式。具体请自行查阅。
十三:通配符
SELECT Paragraph FROM tableName WHERE Paragraph2 = ‘PartWeNeed’ – 仅取得字段数据完全为 ‘PartWeNeed’ 的数据 SELECT Paragraph FROM tableName WHERE Paragraph2 LIKE ‘%PartWeNeed%’ – 可取得字段数据包含 ‘PartWeNeed’ 的数据 SELECT Paragraph FROM tableName WHERE Paragraph2 LIKE ‘[A-G]%’ – 可取得首字母为A到G的数据 SELECT Paragraph FROM tableName WHERE Paragraph2 LIKE ‘[ACG]%’ – 可取得首字母为A或者C或G的数据 SELECT Paragraph FROM tableName WHERE Paragraph2 LIKE ‘[A-GN]%’ – 可取得首字母为A到G,或为N的数据 SELECT Paragraph FROM tableName WHERE Paragraph2 LIKE ‘[^G]%’ – 可取得首字母不为G的数据 SELECT Paragraph FROM tableName WHERE Paragraph2 LIKE ’M_o’ – 可取得第一个字母为M,第三个字母为o的数据,例如 MMo,Mio均会返回 SELECT Paragraph FROM tableName WHERE Paragraph2 LIKE ‘%[%]%’ – 可取得拥有%百分号的数据
1:% 通配符可表示不定长度的字符串 2:【】 内数据表示枚举集合,表示一个字符 3:- 两端表示一定范围 4:_ 表示一个不定的字符 5:[%] 表示单一的字符’%‘百分号
十四:发音匹配(考虑到实用性,该部分略,有兴趣的可去查获在哦 DEIFFERNCE, SOUNDEX 关键字)
十五:删除空格
SELECT RTRIM( Paragraph ) FROM tableName – 取得字段数据并去除该数据字符串后的所有空格 SELECT LTRIM( RTRIM( Paragraph )) FROM tableName – 取得字段数据并去除该数据字符串前后的所有空格
1:SQL里,CHAR类型会自动在字符串后填充0,我们可以使用该方法去除空格。
十六:时间类型细解
SELECT * FROM newTable WHERE DateParagraph = ‘12/11/2009’ – 取出2009年11月12日0时0分0秒0毫秒的数据 SELECT * FROM newTable WHERE DateParagraph >= ‘12/11/2009’ AND DateParagraph <= ‘13/11/2009’ – 取出2009年11月12日一整天的数据 SELECT * FROM newTable WHERE DateParagraph = ‘12/11/2009%’ – 结果同上句,本句中的通配符代表是的所有的时间信息,即取出2009年11月12日一整天任何时间的数据
1:DATEPART关键字可以获取DATE数据中的部分信息,例如,单独取出年份等,不详解。 2:DATEDIFF关键字可以比较两个DATE数据中的信息,DATEADD关键字可进行年月日的增加更变,不详解。
十七:邮件发送
若安装了邮件服务器,那么配置一下就可以使用SQL进行邮件发送。不详解。