首页
网站首页
公司简介
资讯中心
推荐内容
返回顶部
Server远程连接,2008从入门到精通
发布时间:2019-12-28 20:36
浏览次数:

一.概念

  在介绍资源等待PAGEIOLATCH之前,先来了解下从实例级别来分析的各种资源等待的dmv视图sys.dm_os_wait_stats。它是返回执行的线程所遇到的所有等待的相关信息,该视图是从一个实际级别来分析的各种等待,它包括200多种类型的等待,需要关注的包括PageIoLatch(磁盘I/O读写的等待时间),LCK_xx(锁的等待时间),WriteLog(日志写入等待),PageLatch(页上闩锁)Cxpacket(并行等待)等以及其它资源等待排前的。 

  1.  下面根据总耗时排序来观察,这里分析的等待的wait_type 不包括以下

SELECT  wait_type ,
        waiting_tasks_count,
        signal_wait_time_ms ,
        wait_time_ms,
        max_wait_time_ms
FROM    sys.dm_os_wait_stats
WHERE   wait_time_ms > 0
        AND wait_type NOT IN ( 'CLR_SEMAPHORE', 'CLR_AUTO_EVENT',
                               'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE',
                               'SLEEP_TASK', 'SLEEP_SYSTEMTASK',
                               'SQLTRACE_BUFFER_FLUSH', 'WAITFOR',
                               'LOGMGR_QUEUE', 'CHECKPOINT_QUEUE',
                               'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT',
                               'BROKER_TO_FLUSH', 'BROKER_TASK_STOP',
                               'CLR_MANUAL_EVENT',
                               'DISPATCHER_QUEUE_SEMAPHORE',
                               'FT_IFTS_SCHEDULER_IDLE_WAIT',
                               'XE_DISPATCHER_WAIT', 'XE_DISPATCHER_JOIN',
                               'SQLTRACE_INCREMENTAL_FLUSH_SLEEP' )
ORDER BY signal_wait_time_ms DESC

  下图排名在前的资源等待是重点需要去关注分析:

图片 1

  通过上面的查询就能找到PAGEIOLATCH_x类型的资源等待,由于是实例级别的统计,想要获得有意义数据,就需要查看感兴趣的时间间隔。如果要间隔来分析,不需要重启服务,可通过以下命令来重置

DBCC SQLPERF ('sys.dm_os_wait_stats', CLEAR);  

  wait_type:等待类型
  waiting_tasks_count:该等待类型的等待数
  wait_time_ms:该等待类型的总等待时间(包括一个进程悬挂状态(Suspend)和可运行状态(Runnable)花费的总时间)
  max_wait_time_ms:该等待类型的最长等待时间
  signal_wait_time_ms:正在等待的线程从收到信号通知到其开始运行之间的时差(一个进程可运行状态(Runnable)花费的总时间)
  io等待时间==wait_time_ms - signal_wait_time_ms

XML查询技术

XML文档以一个纯文本的形式存在,主要用于数据存储。不但方便用户读取和使用,而且使修改和维护变得更容易。

置SQLServer,允许远程连接

按照上面的文章一步步配置后,远程连接出现下面所示的报错(Navicat 和 SQL Server Management Studio)

图片 2

图片 3

SQL Server Management Studio的报错信息为:

在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: Named Pipes Provider, error: 40 - 无法打开到 SQL Server 的连接) (Microsoft SQL Server,错误: 53)。

后来查了很多解决方法,均以失败告终。后来无意间意识到,远程数据库所在云服务器的安全组未开放对该端口的远程访问权限,以我所用的阿里云为例,在安全组->配置规则->快速创建规则 中,添加MS SQL的1433端口。若为新创建的安全组,还需重启服务器才可生效。

图片 4

 

昨晚完成了Web端新增图书信息的功能,现在就差DB的具体实现了。

二. PAGEIOLATCH_x

  2.1 什么是Latch

    在sql server里latch是轻量级锁,不同于lock。latch是用来同步sqlserver的内部对象(同步资源访问),而lock是用来对于用户对象包括(表,行,索引等)进行同步,简单概括:Latch用来保护SQL server内部的一些资源(如page)的物理访问,可以认为是一个同步对象。而lock则强调逻辑访问。比如一个table,就是个逻辑上的概念。关于lock锁这块在"sql server 锁与事务拨云见日"中有详细说明。

  2.2 什么是PageIOLatch 

  当查询的数据页如果在Buffer pool里找到了,则没有任何等待。否则就会发出一个异步io操作,将页面读入到buffer pool,没做完之前,连接会保持在PageIoLatch_ex(写)或PageIoLatch_sh(读)的等待状态,是Buffer pool与磁盘之间的等待。它反映了查询磁盘i/o读写的等待时间。
  当sql server将数据页面从数据文件里读入内存时,为了防止其他用户对内存里的同一个数据页面进行访问,sql server会在内存的数据页同上加一个排它锁latch,而当任务要读取缓存在内存里的页面时,会申请一个共享锁,像是lock一样,latch也会出现阻塞,根据不同的等待资源,等待状态有如下:PAGEIOLATCH_DT,PAGEIOLATCH_EX,PAGEIOLATCH_KP,PAGEIOLATCH_SH,PAGEIOLATCH_UP。重点关注PAGEIOLATCH_EX(写入)和PAGEIOLATCH_SH(读取)二种等待。

2.1  AGEIOLATCH流程图

  有时我们分析当前活动用户状态下时,一个有趣的现象是,有时候你发现某个SPID被自己阻塞住了(通过sys.sysprocesses了查看) 为什么会自己等待自己呢? 这个得从SQL server读取页的过程说起。SQL server从磁盘读取一个page的过程如下:

图片 5

图片 6

  (1):由一个用户请求,获取扫描X表,由Worker x去执行。

  (2):在扫描过程中找到了它需要的数据页同1:100。

  (3):发面页面1:100并不在内存中的数据缓存里。

  (4):sql server在缓冲池里找到一个可以存放的页面空间,在上面加EX的LATCH锁,防止数据从磁盘里读出来之前,别人也来读取或修改这个页面。

  (5):worker x发起一个异步i/o请求,要求从数据文件里读出页面1:100。

  (6):由于是异步i/o(可以理解为一个task子线程),worker x可以接着做它下面要做的事情,就是读出内存中的页面1:100,读取的动作需要申请一个sh的latch。

  (7):由于worker x之前申请了一个EX的LATCH锁还没有释放,所以这个sh的latch将被阻塞住,worker x被自己阻塞住了,等待的资源就是PAGEIOLATCH_SH。

  最后当异步i/o结束后,系统会通知worker x,你要的数据已经写入内存了。接着EX的LATCH锁释放,worker x申请得到了sh的latch锁。

总结:首先说worker是一个执行单元,下面有多个task关联Worker上, task是运行的最小任务单元,可以这么理解worker产生了第一个x的task任务,再第5步发起一个异步i/o请求是第二个task任务。二个task属于一个worker,worker x被自己阻塞住了。 关于任务调度了解查看sql server 任务调度与CPU

 2.2 具体分析

  通过上面了解到如果磁盘的速度不能满足sql server的需要,它就会成为一个瓶颈,通常PAGEIOLATCH_SH 从磁盘读数据到内存,如果内存不够大,当有内存压力时候它会释放掉缓存数据,数据页就不会在内存的数据缓存里,这样内存问题就导致了磁盘的瓶颈。PAGEIOLATCH_EX是写入数据,这一般是磁盘的写入速度明显跟不上,与内存没有直接关系。

下面是查询PAGEIOLATCH_x的资源等待时间:

select wait_type,
waiting_tasks_count,
wait_time_ms ,
max_wait_time_ms,
signal_wait_time_ms
from sys.dm_os_wait_stats
where wait_type like 'PAGEIOLATCH%' 
order by wait_type

下面是查询出来的等待信息:

PageIOLatch_SH 总等待时间是(7166603.0-15891)/1000.0/60.0=119.17分钟,平均耗时是(7166603.0-15891)/297813.0=24.01毫秒,最大等待时间是3159秒。

PageIOLatch_EX 总等待时间是(3002776.0-5727)/1000.0/60.0=49.95分钟,    平均耗时是(3002776.0-5727)/317143.0=9.45毫秒,最大等待时间是1915秒。

图片 7

关于I/O磁盘 sys.dm_io_virtual_file_stats 函数也做个参考

SELECT  
       MAX(io_stall_read_ms) AS read_ms,
         MAX(num_of_reads) AS read_count,
       MAX(io_stall_read_ms) / MAX(num_of_reads) AS 'Avg Read ms',
         MAX(io_stall_write_ms) AS write_ms,
        MAX(num_of_writes) AS write_count,
         MAX(io_stall_write_ms) /  MAX(num_of_writes) AS 'Avg Write ms'
FROM    sys.dm_io_virtual_file_stats(null, null)
WHERE   num_of_reads > 0 AND num_of_writes > 0 

图片 8

  总结:PageIOLatch_EX(写入)跟磁盘的写入速度有关系。PageIOLatch_SH(读取)跟内存中的数据缓存有关系。通过上面的sql统计查询,从等待的时间上看,并没有清晰的评估磁盘性能的标准,但可以做评估基准数据,定期重置,做性能分析。要确定磁盘的压力,还需要从windows系统性能监视器方面来分析。 关于内存原理查看”sql server 内存初探“磁盘查看"sql server I/O硬盘交互" 。

XML数据类型

XML是SQL Server中内置的数据类型,可用于SQL语句或者作为存储过程的参数。用户可以直接在数据库中存储、查询和管理XML文件。XML数据类型还能保存整个XML文档。XML数据类型和其他数据类型不存在根本上的差别,可以把它用在任何普通SQL数据类型可以使用的地方。
示例1:创建一个XML变量并用XML填充

DECLARE @doc XML
SELECT @doc='<Team name="Braves" />';

示例2:创建XML数据类型列

CREATE TABLE t1(
column1 INT,
column2 XML,
CONSTRAINT pk_column1 PRIMARY KEY(column1));

在上面的示例中,column2列是XML数据类型列。
示例3:不能将XML数据类型列设置为主键或外键

CREATE TABLE t1(
column1 INT,
column2 XML,
CONSTRAINT pk_column1 PRIMARY KEY(column2));

执行上面的代码,报错如下:
消息1919,级别16,状态1,第1 行
表't1' 中的列'column2' 的类型不能用作索引中的键列。
消息1750,级别16,状态0,第1 行
无法创建约束。请参阅前面的错误消息。
XML数据类型的使用限制
只有STRING数据类型才能转换成XML。
XML列不能应用于GROUP BY语句中
XML数据类型存储的数据不能超过2GB
XML数据类型字段不能被设置成主键或者外键或称为其一部分。
Sql_variant数据类型字段的使用不能把XML数据类型作为种子类型。
XML列不能指定为唯一的。
COLLATE子句不能被使用在XML列上。
存储在数据库中的XML仅支持128级的层次。
表中最对只能拥有32个XML列。
XML列不能加入到规则中。
唯一可应用于XML列的内置标量函数是ISNULL和COALESCE。
具有XML数据类型列的表不能有一个超过15列的主键。

因为我把Book相关的信息拆分的比较多,所以更新有点小麻烦。

类型化的XML和非类型化的XML

可以创建xml类型的变量,参数和列,或者将XML架构集合和xml类型的变量、参数或列关联,这种情况下,xml数据类型实例称之为类型化xml实例。否则XML实例称为非类型化的实例。

首先,我需要创建一个Book Type的Matter;

XML数据类型方法

XML数据类型共有5种方法
query():执行一个XML查询并返回查询结果(返回一个XML数据类型)。
示例4

DECLARE @xmlDoc XML--声明XML类型的变量@xmlDoc
SET @xmlDoc='<students>
    <class name="数学" NO="8501">
        <student>
            <name>李林</name>
            <sex>男</sex>
            <age>16</age>
            <address>江苏</address>
        </student>
    </class>
</students>'--将XML实例分配给变量@xmlDoc
SELECT @xmlDoc.query('/students/class/student') AS test
--用query()查询@xmlDoc变量实例中标签<student>的子元素

查询结果如图所示
图片 9
点击查询结果
图片 10
如想查询标签

DECLARE @addr XML--声明一个XML类型变量@addr
SET @addr='/students/class/student'
SELECT @addr.exist('/students/class="江苏"') AS 返回值

结果如图所示
图片 11

注:exsit()方法的参数不必做精确定位

Value():计算一个查询并从XML中返回一个简单的值(只能返回单个值,且该值为非XML数据类型)。
Value()方法有2个参数XQuery和SQLType,XQuery参数表示命令要从XML实例内部查询数据的具体位置,SQLType参数表示value()方法返回的值的首选数据类型。
示例6

DECLARE @xmlDoc XML--声明XML类型的变量@xmlDoc
DECLARE @classID INT--声明INT类型的变量@classID
SET @xmlDoc='<students>
    <class name="数学" NO="8501">
        <student>
            <name>李林</name>
            <sex>男</sex>
            <age>16</age>
            <address>江苏</address>
        </student>
    </class>
</students>'--将XML实例分配给变量@xmlDoc
SET @classID=@xmlDoc.value('(/students/class/@NO)[1]','INT')
--将value()方法返回值赋值给变量@classID
SELECT @classID AS classID

查询结果如图所示
图片 12

注:SQLType不能是XML数据类型,公共语言运行时(CLR)用户定义类型,image,text,ntext或sql_variant数据类型,但可以是用户自定义数据类型SQL。

Modify():在XML文档的适当位置执行一个修改操作。它的参数XML_DML代表一串字符串,根据此字符串表达式来更新XML文档的内容。
示例7:在@xmlDoc的实例中,元素

DECLARE @xmlDoc XML--声明XML类型的变量@xmlDoc
SET @xmlDoc='<students>
    <class name="数学" NO="8501">
        <student>
            <name>李林</name>
            <sex>男</sex>
            <age>16</age>
            <address>江苏</address>
        </student>
    </class>
</students>'
SELECT @xmlDoc AS '插入节点前信息'
SET @xmlDoc.modify('insert <学历>本科</学历> after (students/class/student/age)[1]')
SELECT @xmlDoc AS '插入节点后信息'

查询结果插入节点后信息如图所示
图片 13

注:modify()方法的参数中insert和其他关键字必须小写,否则会报错

Nodes():允许把XML分解到一个表结构中。此方法将XML数据类型实例拆分为关系数据,并返回包含原始XML数据的行集。
示例8:依然用@locat参数的实例来示范

DECLARE @locat XML--声明XML变量@locat
SET @locat=
'<root>
    <location locationID="8">
        <step>8的步骤</step>
        <step>8的步骤</step>
        <step>8的步骤</step>
    </location>
    <location locationID="9">
        <step>9的步骤</step>
        <step>9的步骤</step>
        <step>9的步骤</step>
    </location>
    <location locationID="10">
        <step>10的步骤</step>
        <step>10的步骤</step>
        <step>10的步骤</step>
    </location>
    <location locationID="11">
        <step>11的步骤</step>
        <step>11的步骤</step>
        <step>11的步骤</step>
    </location>
</root>'--@locat变量的实例

SELECT T.Loc.query('.') AS result
FROM @locat.nodes('/root/location') T(Loc)
GO

查询结果如下图所示
图片 14

然后,将图片路径保存到FileBank中,并返回FileBankID;

XQuery简介

XQuery是一种查询语言,可以查询结构化或者半结构化的数据。SQL Server 2008中对XML数据类型提供了支持,可以存储XML文档,然后使用XQuery语言进行查询。

继续,插入Publisher信息(需要判断name不存在才会insert),然后返回PublisherID;

FOR XML子句

通过在SELECT语句中使用FOR XML子句可以把数据库表中的数据检索出来并生成XML格式。SQL Server 2008支持FOR XML的四种模式,分别是RAW模式,AUTO模式,EXPLICIT模式和PATH模式。

 1 CREATE PROCEDURE [base].[Publisher#Insert](@json nvarchar(max), @id int out)
 2 WITH ENCRYPTION
 3 AS
 4 BEGIN
 5 ...
 6 
 7         declare    @name nvarchar(100);
 8         select    @name=Publisher from openjson(@json, '$') with (Publisher nvarchar(100))
 9 
10         -- insert Publisher
11         insert    base._Publisher(Name)select @name
12         where    not exists(select 1 from base._Publisher p where p.Name=@name);
13 
14         select    @id=ID from base.Publisher#Raw() where Name=@name;
15 ...
16 END
FOR XML RAW

将表转换成元素名称是row,属性名称为列名或者列的别名。
示例9:将Student表转换为XML格式(FOR XML RAW)
Student表的数据如图所示
图片 15
执行语句:

SELECT * FROM Student FOR XML RAW;

查询结果如图所示
图片 16
图片 17

 

FOR XML AUTO

使用表名称作为元素名称,使用列名称作为属性名称,SELECT关键字后面列的顺序用于XML文档的层次。
示例10:将Student表转换为XML格式(FOR XML AUTO)
执行语句:

SELECT * FROM Student FOR XML AUTO;

查询结果如图所示
图片 18
图片 19

继续,插入Binding信息(也需要判断name不存在才insert),返回BindingID;

FOR XML EXPLICIT

允许用户显式地定义XML树的形状,不受AUTO模式中的种种限制。不能将FOR XML EXPLICIT直接用在SELECT子句中。
示例11:将xmlTest表转换为XML格式(FOR XML EXPLICIT)
XmlTest表的数据如图所示
图片 20

SELECT DISTINCT 1 AS TAG,--指定顶级层级序号1
NULL AS PARENT,--该层级没有父级
NULL AS '班级信息!1!',
NULL AS '班级信息!2!班级',
NULL AS '班级信息!2!班级类型',
NULL AS '班级信息!2!班主任',
NULL AS '学生信息!3!学号!Element',
NULL AS '学生信息!3!学生姓名!Element',
NULL AS '学生信息!3!性别!Element',
NULL AS '学生信息!3!总分!Element'--设置所有层级元素和属性命名,暂时不对这些元素赋值
--例如在“学生信息!3!总分!Element”格式中,学生信息是元素名,3表示该元素所处层级,总分表示属性名
--Element指出生成以属性单独为一行的XML格式
UNION ALL--层级之间用UNION ALL相连
SELECT DISTINCT 2 AS TAG,--指定二级层级序号2
1 AS PARENT,--父级序号是序号为1的层级
NULL,--在层级的代码中已列出了所有层级元素和属性命名,因此这里给元素和属性做赋值。这句语句对应层级代码中“NULL AS '班级信息!1!'”,说明我希望该元素作为独立成行的标签,没有赋值。
班级,--对层级中的“NULL AS '班级信息!2!班级'”赋值,将xmlTest表中的班级赋值给属性班级
班级类型,--对层级中的“NULL AS '班级信息!2!班级类型'”赋值,将xmlTest表中的班级赋值给属性班级类型
班主任,--同上
NULL,--这句语句开始对应的是层级的属性,因此在层级的代码中不做赋值,在下面层级的代码中做赋值
NULL,
NULL,
NULL
FROM xmlTest--指出上面赋值的数据源来自于xmlTest表
UNION ALL--各个层级之间用UNION ALL连接
SELECT 3 AS TAG,--指定3级层级序号3
2 AS PARENT,--父级是序号为2的层级
NULL,--对应层级的”NULL AS '班级信息!1!'“语句,不希望它有值,所以不做赋值
NULL,--这三个NULL对应层级的各个属性,在层级的代码中已经做过赋值,因此在这里不做赋值
NULL,
NULL,
学号,--对应层级1代码中的层级3属性,在层级代码3中进行赋值
学生姓名,
性别,
年级总分
FROM xmlTest
FOR XML EXPLICIT;--将上述查询转换为XML,不能漏掉,否则结果会以表格形式显示

查询结果如图所示
图片 21
图片 22
在结果图中我们发现,红框中3个班级信息列在一起,而所有学生都列在高一3班下,这不是我们想要的结果,我们希望每个班级对应自己的学生。那么如何解决此类问题呢,这涉及到排序。

注:如果层级中有多个数据完全重复,可以在该层级对应的代码前加DISTINCT关键字去除重复元素。

首先删除代码行末的FOR XML EXPLICIT语句,仅仅执行剩下的部分,使结果以表格形式呈现,那么结果如下
图片 23
这个表格每行的顺序也代表了该表格转化为XML文档后内容显示顺序。图中层级2(TAG=2)的几行,位置都在一起,这也就是为什么层级3的所有数据都在高一3班下面了。我们需要对表格每行的顺序进行调整,使学生所在行按照xmlTest表中的数据逻辑分散在班级行之下。但是根据上面的表格发现,不管按照什么字段排序,都不可能达到效果。
正确代码如下

SELECT DISTINCT 1 AS TAG,
NULL AS PARENT,
NULL AS '班级信息!1!',
NULL AS '班级信息!2!班级',
NULL AS '班级信息!2!班级类型',
NULL AS '班级信息!2!班主任',
NULL AS '学生信息!3!学号!Element',
NULL AS '学生信息!3!学生姓名!Element',
NULL AS '学生信息!3!性别!Element',
NULL AS '学生信息!3!总分!Element'
UNION ALL
SELECT DISTINCT 2 AS TAG,
1 AS PARENT,
NULL,
班级,
班级类型,
班主任,
NULL,
NULL,
NULL,
NULL
FROM xmlTest
UNION ALL
SELECT 3 AS TAG,
2 AS PARENT,
NULL,
班级,
班级类型,
班主任,
学号,
学生姓名,
性别,
年级总分
FROM xmlTest
ORDER BY [班级信息!2!班级],[学生信息!3!学号!Element]
FOR XML EXPLICIT;

对比第一次代码,我们发现上面的代码不止在行末对数据按元素属性进行了排序,还在赋值的代码中有所改动。在层级1代码中完全没有改动,因为层级1的代码作用是设置XML格式的,对数据排序没有影响。在下面几个层级的赋值部分,每个层级的代码中都对上面几个层级的元素重复赋值,这样做使结果的表格中不再有那么多属性值是NULL,可以方便排序。最后再按照元素[班级信息!2!班级]和[学生信息!3!学号!Element]排序。让我们看看结果如何。
运行上面的代码,但不运行FOR XML EXPLICIT语句,看看表格中数据内容和行顺序是否改变
图片 24
如图所示,发现行数据和学生数据的顺序显示正确。运行所有代码得到XML文档,结果如图所示
图片 25
由于XML文档内容过长,不贴图了,直接复制所有XML内容展示一下。

<班级信息>
  <班级信息 班级="高一1班" 班级类型="创新班" 班主任="李玉虎">
    <学生信息>
      <学号>20180101</学号>
      <学生姓名>李华</学生姓名>
      <性别>男</性别>
      <总分>5.680000000000000e+002</总分>
    </学生信息>
    <学生信息>
      <学号>20180103</学号>
      <学生姓名>孙丽</学生姓名>
      <性别>女</性别>
      <总分>3.390000000000000e+002</总分>
    </学生信息>
    <学生信息>
      <学号>20180108</学号>
      <学生姓名>吴伟</学生姓名>
      <性别>男</性别>
      <总分>5.280000000000000e+002</总分>
    </学生信息>
  </班级信息>
  <班级信息 班级="高一2班" 班级类型="重点班" 班主任="姜杰">
    <学生信息>
      <学号>20180102</学号>
      <学生姓名>张三</学生姓名>
      <性别>男</性别>
      <总分>6.270000000000000e+002</总分>
    </学生信息>
    <学生信息>
      <学号>20180104</学号>
      <学生姓名>袁康</学生姓名>
      <性别>男</性别>
      <总分>4.820000000000000e+002</总分>
    </学生信息>
    <学生信息>
      <学号>20180106</学号>
      <学生姓名>赵四</学生姓名>
      <性别>男</性别>
      <总分>5.680000000000000e+002</总分>
    </学生信息>
  </班级信息>
  <班级信息 班级="高一3班" 班级类型="提高班" 班主任="师从光">
    <学生信息>
      <学号>20180105</学号>
      <学生姓名>王婷</学生姓名>
      <性别>女</性别>
      <总分>7.610000000000000e+002</总分>
    </学生信息>
    <学生信息>
      <学号>20180107</学号>
      <学生姓名>周其</学生姓名>
      <性别>女</性别>
      <总分>3.480000000000000e+002</总分>
    </学生信息>
    <学生信息>
      <学号>20180109</学号>
      <学生姓名>甄诚</学生姓名>
      <性别>女</性别>
      <总分>7.020000000000000e+002</总分>
    </学生信息>
  </班级信息>
</班级信息>

将上面的结果对比一下原始xmlTest表,看看每个班级和它下属学生的层级关系是否有误。

注:写FOR XML EXPLICIT代码要注意,层级1的代码中先设置层级结构,不要先急着赋值。在下属层级的代码中对层级1中的代码进行赋值,最好重复赋值,不然就会出现文中的排序问题。如果某个层级出现重复数据,在该层级的代码前加DISTINCT关键字。解决排序问题最好的办法是对各个层级的属性重复赋值并在末尾用ORDER BY按层级属性排序。

仔细观察上面的XML文档,发现总分属性的值是个float类型,要把它转换成int,只需要把层级3中对总分的赋值代码改成CAST(年级总分 AS int)
图片 26

 1 CREATE PROCEDURE [base].[Binding#Insert](@json nvarchar(max), @id int out)
 2 WITH ENCRYPTION
 3 AS
 4 BEGIN
 5 ...
 6 
 7         declare    @name nvarchar(100);
 8         select    @name=Binding from openjson(@json, '$') with (Binding nvarchar(100))
 9 
10         -- insert Binding
11         insert    base._Binding(Name)select @name
12         where    not exists(select 1 from base._Binding p where p.Name=@name);
13 
14         select    @id=ID from base.Binding#Raw() where Name=@name;
15 
16 ...
17 END
FOR XML PATH

PATH模式提供了一种较简单的方法来混合元素及属性。在PATH模式中,列名或列别名被作为XPATH表达式来处理,这些表达式指定了如何将值映射到XML中。默认情况下,PATH模式为每一样自动生成

 

友情链接: 网站地图
Copyright © 2015-2019 http://www.nflfreepicks.net. 新葡萄京娱乐场网址有限公司 版权所有