Auditing SQL Server SQL Statements

Jun 07, 2016 pm 02:50 PM
server sql

“谁把我的表给删拉”,”谁删了整个表阿”…碰到这种棘手的情况,你如果没有预先做好准备,真的是头都要急炸了。那怎么能抓出这个”凶手”呢?SQL Trace, SQL Profile,SQL Trigger,Extended Events等着伺候你呢,更别说CLR,Service Broker等重量级武器了

“谁把我的表给删拉”,”谁删了整个表阿”…碰到这种棘手的情况,你如果没有预先做好准备,真的是头都要急炸了。那怎么能抓出这个”凶手”呢?SQL Trace, SQL Profile,SQL Trigger,Extended Events等着伺候你呢,更别说CLR,Service Broker等重量级武器了,别急!

工具虽好,但是也得用得贴合场景才能发挥作用,要不然跟你的SQL Server抢IO,那就得不偿失了。比如高频的OLTP场合,你还用TRIGGER把大量的DML语句都写到当前数据库去,那不是给数据库增加一倍工作量么。当然控制好权限,做好测试也能保证你的数据安全。这不妨碍我们讨论auditing SQL。

SQL Profiler是基于SQL Trace的,而SQL Trace是会被更高版本的SQL Server给逐渐摒弃的,所以我们就只讨论一个就可以了。一开始我知道 SQL Profiler是可以可视化监控即时的SQL Server活动的,但是缺点是不能保存或者自动执行,需要人工干预。经过研究,它是可以自动保存截取结果的。

让我们认识下“源”:想要抓“破坏分子”,首先要知道“破环分子”的标示有哪些,漏抓,错抓,都是失手的表现。访问SQL SERVER的方式有很多种,有ADO.NET, JDBC, SQL SERVER Management Studio, ODBC等各种方法,也有 Ad-hoc SQL, Stored Procedure等表现形式,是否每一种的方式都有各自不同的格式呢?最好的方法就是针对每种方式都来做个例子验证下。

首先最简单的SSMS方式,我们将SQL Profiler限制到某一个数据库,lenistest4。 在SSMS里面输入:

<code class=" hljs rust"><span class="hljs-keyword">use</span> lenistest4

go</code>
ログイン後にコピー

SQL Profiler显示的是SQL:BatchCompleted。

这里写图片描述
这里与有没有go无关。当你选中一块SQL区域并执行,其中如果有go那就有关系了,比如:

<code class=" hljs sql"><span class="hljs-operator"><span class="hljs-keyword">select</span> top <span class="hljs-number">10</span> * <span class="hljs-keyword">from</span> sys.tables

<span class="hljs-keyword">go</span>

<span class="hljs-keyword">select</span> top <span class="hljs-number">10</span> * <span class="hljs-keyword">from</span> dbo.region

<span class="hljs-keyword">go</span></span></code>
ログイン後にコピー

这里写图片描述

这里一个go分割了一个batch。最后一个go没有意义,我们提交了一段代码,这段代码相当于是一个大batch,如果中间有go,那这个go 就代表了一个子batch。

那么用动态语句,会有什么Trace格式呢:

<code class=" hljs css"><span class="hljs-tag">declare</span> <span class="hljs-at_rule">@<span class="hljs-keyword">sqlstatement</span> <span class="hljs-function">nvarchar(max)</span> = N<span class="hljs-string">'select top 10 * from dbo.region'</span> </span>;

<span class="hljs-tag">exec</span> <span class="hljs-tag">sp_executesql</span> <span class="hljs-at_rule">@<span class="hljs-keyword">sqlstatement</span></span></code>
ログイン後にコピー

这里写图片描述

这里有SQL:Batch*, SQL:Stmt*,SP:Stmt, SQL:Stmt*代表的是一系列的SQL命令,比如declare, set等;SP:Stmt*代表了stored procedure的范围内语句。

<code class=" hljs vbnet"><span class="hljs-keyword">declare</span> @sqlstatement nvarchar(max) = N<span class="hljs-comment">'</span>

<span class="hljs-keyword">declare</span> @regionName varchar(<span class="hljs-number">20</span>) = <span class="hljs-comment">''China''</span>

<span class="hljs-keyword">select</span> top <span class="hljs-number">10</span> * <span class="hljs-keyword">from</span> dbo.region

<span class="hljs-keyword">where</span> regionName = @regionName<span class="hljs-comment">' ;</span>

exec sp_executesql @sqlstatement</code>
ログイン後にコピー

这里写图片描述
上面这段SQL,验证了SQL命令select和declare是不是都被看作是SP:Stmt* ? 其实在一个batch里面,SQL命令里面DML语句也是被当作Statement来处理的。

如果在动态SQL里面有go是不是也会有SP:Batch*? 我们接着往下看:

<code class=" hljs vbnet"><span class="hljs-keyword">declare</span> @sqlstatement nvarchar(max) = N<span class="hljs-comment">'</span>

<span class="hljs-keyword">declare</span> @regionName varchar(<span class="hljs-number">20</span>) = <span class="hljs-comment">''China''</span>

<span class="hljs-keyword">select</span> top <span class="hljs-number">10</span> * <span class="hljs-keyword">from</span> dbo.region

<span class="hljs-keyword">where</span> regionName = @regionName;

go

<span class="hljs-keyword">declare</span> @regionName2 varchar(<span class="hljs-number">20</span>) = <span class="hljs-comment">''England''</span>

<span class="hljs-keyword">select</span> top <span class="hljs-number">10</span> * <span class="hljs-keyword">from</span> dbo.region

<span class="hljs-keyword">where</span> regionName = @regionName2

<span class="hljs-comment">' ;</span>

exec sp_executesql @sqlstatement</code>
ログイン後にコピー

Msg 102, Level 15, State 1, Line 12

Incorrect syntax near ‘go’.

可以看到go是不能用在动态语句里面的。

为了验证SP:Stmt*是不是指的是存储过程里面的语句,我们先创建一个stored procedure,然后再执行它:

<code class=" hljs sql"><span class="hljs-operator"><span class="hljs-keyword">create</span> <span class="hljs-keyword">procedure</span> dbo.getRegionName

<span class="hljs-keyword">as</span>

<span class="hljs-keyword">begin</span>

<span class="hljs-keyword">declare</span> @regionName <span class="hljs-keyword">varchar</span>(<span class="hljs-number">20</span>) = <span class="hljs-string">'China'</span>

<span class="hljs-keyword">select</span> top <span class="hljs-number">10</span> * <span class="hljs-keyword">from</span> dbo.region

<span class="hljs-keyword">where</span> regionName = @regionName

<span class="hljs-keyword">declare</span> @regionNamex <span class="hljs-keyword">varchar</span>(<span class="hljs-number">20</span>) = <span class="hljs-string">'England'</span>

<span class="hljs-keyword">select</span> top <span class="hljs-number">10</span> * <span class="hljs-keyword">from</span> dbo.region

<span class="hljs-keyword">where</span> regionName = @regionNamex

<span class="hljs-keyword">end</span>

<span class="hljs-keyword">exec</span> dbo.getRegionName</span></code>
ログイン後にコピー

这里写图片描述
正是如此 !综上所述, SQL:Batch* , 这里的batch相当于是个scope,一个大的执行空间,里面的所有 SQL 语句都是statement,包括DML,DDL等一系列 T-SQL语句 ;而SP:Stmt*又是存储过程的执行空间,里面所有的 T-SQL语句都是statement。

下面看段c#调用这个stored procedure,看看trace是如何识别的:

<code class=" hljs vala"><span class="hljs-keyword">using</span> System;

<span class="hljs-keyword">using</span> System.Collections.Generic;

<span class="hljs-keyword">using</span> System.Linq;

<span class="hljs-keyword">using</span> System.Text;

<span class="hljs-keyword">using</span> System.Threading.Tasks;

<span class="hljs-keyword">using</span> System.Data.SqlClient;

<span class="hljs-keyword">using</span> System.Data.SqlTypes;

<span class="hljs-keyword">using</span> System.Data;

<span class="hljs-class"><span class="hljs-keyword">namespace</span> <span class="hljs-title">AccessLenistest4DB</span>

{</span>

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>

    {</span>

        <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> Main(<span class="hljs-keyword">string</span>[] args)

        {

            SqlConnection<span class="hljs-constant"> ICONN </span>= <span class="hljs-keyword">new</span> SqlConnection(@<span class="hljs-string">"data source = (localhost);initial catalog = lenistest4 ;user id = sa; password = sas;"</span>);

            SqlCommand icmd = <span class="hljs-keyword">new</span> SqlCommand();

            icmd.Connection = ICONN;

            icmd.CommandType = System.Data.CommandType.StoredProcedure;

            icmd.CommandText = <span class="hljs-string">"dbo.getRegionName"</span>;

            SqlDataAdapter ida = <span class="hljs-keyword">new</span> SqlDataAdapter(icmd);

            DataSet localds = <span class="hljs-keyword">new</span> DataSet();

            <span class="hljs-keyword">try</span>

            {

                ICONN.Open();

                ida.Fill(localds);

            }

            <span class="hljs-keyword">catch</span>(SqlException se)

            {

                Console.Write(se.ToString());

            }

        }

    }

}</code>
ログイン後にコピー

这里写图片描述
这儿多了个RPC, remote procedure call。其他都一样,所以RPC可以看作是一种命名空间,用阿里区别访问协议。这里要区别的是我们调用的是stored procedure,所以会RPC。所以如果我们是用纯SQL来访问数据库,那会不会有 RPC标示呢:

<code class=" hljs vala"><span class="hljs-keyword">using</span> System;

<span class="hljs-keyword">using</span> System.Collections.Generic;

<span class="hljs-keyword">using</span> System.Linq;

<span class="hljs-keyword">using</span> System.Text;

<span class="hljs-keyword">using</span> System.Threading.Tasks;

<span class="hljs-keyword">using</span> System.Data.SqlClient;

<span class="hljs-keyword">using</span> System.Data.SqlTypes;

<span class="hljs-keyword">using</span> System.Data;

<span class="hljs-class"><span class="hljs-keyword">namespace</span> <span class="hljs-title">AccessLenistest4DB</span>

{</span>

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>

    {</span>

        <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> Main(<span class="hljs-keyword">string</span>[] args)

        {

            SqlConnection<span class="hljs-constant"> ICONN </span>= <span class="hljs-keyword">new</span> SqlConnection(@<span class="hljs-string">"data source = (localhost);initial catalog = lenistest4 ;user id = sa; password = sas;"</span>);

            SqlCommand icmd = <span class="hljs-keyword">new</span> SqlCommand();

            icmd.Connection = ICONN;

            icmd.CommandType = System.Data.CommandType.Text;

            icmd.CommandText = <span class="hljs-string">"select * from dbo.region"</span>;

            SqlDataAdapter ida = <span class="hljs-keyword">new</span> SqlDataAdapter(icmd);

            DataSet localds = <span class="hljs-keyword">new</span> DataSet();

            <span class="hljs-keyword">try</span>

            {

                ICONN.Open();

                ida.Fill(localds);

            }

            <span class="hljs-keyword">catch</span>(SqlException se)

            {

                Console.Write(se.ToString());

            }

        }

    }

}</code>
ログイン後にコピー

这里写图片描述
并没有RPC。 事实证明 RPC只出现在客户端语言调用存储过程的例子。

Trace的手段 :“破坏分子”的特征被识别了,接下来就是怎么去抓捕的手段问题了。可以有即时的GUI工具,比如SQL Profiler,Extended Event(SSMS自带),也可以用脚本去抓,并放在特定存储里面供稍后分析使用。

SQL Profiler 是即时的GUI工具很好用,可以保存结果,也可以自定义模板,缺点在于你必须开一个额外的窗口去跟踪,有时候数据量太大,还会影响传输,对多太SQL Server做监控就不怎么容易了,一个一个手工去开窗口,是不是很麻烦 ?

这里有Extended Events可以帮我们用脚本的形式去捕捉这些T-SQL语句,这里有个简单的例子:

  1. 通过 Extended Events ,我们可以监控一段时间内的的 SQL Completed 情况,简要介绍下:

1.1 Extended Events 概念:由一系列自动触发的 event 产生性能数据,经过 event engine 的收集,存放到指定的输出文件,以供后续的分析。

1.2 XE 涉及到的动态管理试图 : sys.dm_xe_packages; sys.dm_xe_objects;sys.dm_xe_sessions

1.3 基本用法:

2.3.1 创建一个 Event Session

<code class=" hljs sql"><span class="hljs-operator"><span class="hljs-keyword">create</span> event <span class="hljs-keyword">session</span> capture_sql_events

<span class="hljs-keyword">on</span> server

<span class="hljs-keyword">add</span> event sqlserver.sql_statement_completed

(

<span class="hljs-keyword">action</span>(sqlserver.sql_text)

)

<span class="hljs-keyword">add</span> target package0.event_file

(

<span class="hljs-keyword">set</span> filename = <span class="hljs-string">'E:\data_bu\capture_sql_events.xel'</span>, metadatafile = <span class="hljs-string">'E:\data_bu\capture_sql_event.xem'</span>

)

<span class="hljs-keyword">go</span></span></code>
ログイン後にコピー

2.3.2 启用这个 Event session 来收集数据

<code class=" hljs sql"><span class="hljs-operator"><span class="hljs-keyword">alter</span> event <span class="hljs-keyword">session</span> capture_sql_events

<span class="hljs-keyword">on</span> server

STATE = <span class="hljs-keyword">start</span>

<span class="hljs-keyword">go</span></span></code>
ログイン後にコピー

2.3.3 停用这个 Event session

<code class=" hljs sql"><span class="hljs-operator"><span class="hljs-keyword">alter</span> event <span class="hljs-keyword">session</span> capture_sql_events

<span class="hljs-keyword">on</span> server

state = stop

<span class="hljs-keyword">go</span></span></code>
ログイン後にコピー

2.3.4 修改一个 session 来增加或者删除对 Event 的监控

<code class=" hljs sql"><span class="hljs-operator"><span class="hljs-keyword">alter</span> event <span class="hljs-keyword">session</span> capture_sql_events <span class="hljs-keyword">on</span> server

<span class="hljs-keyword">add</span> event sqlserver.sql_batch_completed (<span class="hljs-keyword">action</span>(sqlserver.sql_text))

<span class="hljs-keyword">go</span></span></code>
ログイン後にコピー

2.3.5 查看正在运行的 Event Session

<code class=" hljs cs"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> sys.dm_xe_sessions

<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> sys.dm_xe_session_events</code>
ログイン後にコピー

2.3.6 查看收集到的统计数据

<code class=" hljs sql"><span class="hljs-operator"><span class="hljs-keyword">select</span> top <span class="hljs-number">10</span> * <span class="hljs-keyword">from</span> dbo.region

<span class="hljs-keyword">go</span>

<span class="hljs-keyword">select</span> * , <span class="hljs-keyword">cast</span>(event_data <span class="hljs-keyword">as</span> xml) <span class="hljs-keyword">as</span> event_data_xml

<span class="hljs-keyword">from</span> sys.fn_xe_file_target_read_file(<span class="hljs-string">'E:\data_bu\capture_sql_events*.xel'</span>,<span class="hljs-keyword">null</span>,<span class="hljs-keyword">null</span>,<span class="hljs-keyword">null</span>)

<span class="hljs-keyword">where</span> event_data <span class="hljs-keyword">like</span> N<span class="hljs-string">'%region%'</span></span></code>
ログイン後にコピー

从结果集我们可以看到,sql_statement_completed这个Event抓到的结果中,包含了Action中我们指定的内容,还包含了其他的一些统计信息:

<code class=" hljs xml"><span class="hljs-tag"><<span class="hljs-title">event</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"sql_statement_completed"</span> <span class="hljs-attribute">package</span>=<span class="hljs-value">"sqlserver"</span> <span class="hljs-attribute">timestamp</span>=<span class="hljs-value">"2016-05-06T03:29:48.868Z"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"duration"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>0<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"cpu_time"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>0<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"physical_reads"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>0<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"logical_reads"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>2<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"writes"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>0<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"row_count"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>6<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"last_row_count"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>6<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"line_number"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>1<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"offset"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>0<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"offset_end"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>62<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"statement"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>select top 10 * from dbo.region<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"parameterized_plan_handle"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span> /></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"sql_text"</span> <span class="hljs-attribute">package</span>=<span class="hljs-value">"sqlserver"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>select top 10 * from dbo.region

<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">action</span>></span>

<span class="hljs-tag"></<span class="hljs-title">event</span>></span></code>
ログイン後にコピー

我们在Action里面加入对database_name,和plan_handle的捕捉,可以从结果看到又多出来两个元素:

<code class=" hljs sql"><span class="hljs-operator"><span class="hljs-keyword">create</span> event <span class="hljs-keyword">session</span> capture_sql_events

<span class="hljs-keyword">on</span> server

<span class="hljs-keyword">add</span> event sqlserver.sql_statement_completed

(

<span class="hljs-keyword">action</span>(sqlserver.sql_text,sqlserver.database_name,sqlserver.plan_handle)

)

<span class="hljs-keyword">add</span> target package0.event_file

(

<span class="hljs-keyword">set</span> filename = <span class="hljs-string">'E:\data_bu\capture_sql_events.xel'</span>, metadatafile = <span class="hljs-string">'E:\data_bu\capture_sql_event.xem'</span>

)</span></code>
ログイン後にコピー
<code class=" hljs xml"><span class="hljs-tag"><<span class="hljs-title">event</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"sql_statement_completed"</span> <span class="hljs-attribute">package</span>=<span class="hljs-value">"sqlserver"</span> <span class="hljs-attribute">timestamp</span>=<span class="hljs-value">"2016-05-06T03:52:02.524Z"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"duration"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>0<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"cpu_time"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>0<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"physical_reads"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>0<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"logical_reads"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>2<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"writes"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>0<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"row_count"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>6<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"last_row_count"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>6<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"line_number"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>1<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"offset"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>0<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"offset_end"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>62<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"statement"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>select top 10 * from dbo.region<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">data</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"parameterized_plan_handle"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span> /></span>

<span class="hljs-tag"></<span class="hljs-title">data</span>></span>

<span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"plan_handle"</span> <span class="hljs-attribute">package</span>=<span class="hljs-value">"sqlserver"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>06002000448a700f00d62b7a0300000001000000000000000000000000000000000000000000000000000000<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">action</span>></span>

<span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"database_name"</span> <span class="hljs-attribute">package</span>=<span class="hljs-value">"sqlserver"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>lenistest4<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">action</span>></span>

<span class="hljs-tag"><<span class="hljs-title">action</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"sql_text"</span> <span class="hljs-attribute">package</span>=<span class="hljs-value">"sqlserver"</span>></span>

<span class="hljs-tag"><<span class="hljs-title">value</span>></span>select top 10 * from dbo.region

<span class="hljs-tag"></<span class="hljs-title">value</span>></span>

<span class="hljs-tag"></<span class="hljs-title">action</span>></span>

<span class="hljs-tag"></<span class="hljs-title">event</span>></span></code>
ログイン後にコピー
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Hibernate フレームワークにおける HQL と SQL の違いは何ですか? Hibernate フレームワークにおける HQL と SQL の違いは何ですか? Apr 17, 2024 pm 02:57 PM

HQL と SQL は Hibernate フレームワークで比較されます。HQL (1. オブジェクト指向構文、2. データベースに依存しないクエリ、3. タイプ セーフティ)、SQL はデータベースを直接操作します (1. データベースに依存しない標準、2. 複雑な実行可能ファイル)。クエリとデータ操作)。

Oracle SQLでの除算演算の使用法 Oracle SQLでの除算演算の使用法 Mar 10, 2024 pm 03:06 PM

「OracleSQLでの除算演算の使用方法」 OracleSQLでは、除算演算は一般的な数学演算の1つです。データのクエリと処理中に、除算演算はフィールド間の比率を計算したり、特定の値間の論理関係を導出したりするのに役立ちます。この記事では、OracleSQL での除算演算の使用法を紹介し、具体的なコード例を示します。 1. OracleSQL における除算演算の 2 つの方法 OracleSQL では、除算演算を 2 つの異なる方法で実行できます。

Oracle と DB2 の SQL 構文の比較と相違点 Oracle と DB2 の SQL 構文の比較と相違点 Mar 11, 2024 pm 12:09 PM

Oracle と DB2 は一般的に使用される 2 つのリレーショナル データベース管理システムであり、それぞれに独自の SQL 構文と特性があります。この記事では、Oracle と DB2 の SQL 構文を比較し、相違点を示し、具体的なコード例を示します。データベース接続 Oracle では、次のステートメントを使用してデータベースに接続します: CONNECTusername/password@database DB2 では、データベースに接続するステートメントは次のとおりです: CONNECTTOdataba

MyBatis動的SQLタグのSetタグ機能の詳細説明 MyBatis動的SQLタグのSetタグ機能の詳細説明 Feb 26, 2024 pm 07:48 PM

MyBatis 動的 SQL タグの解釈: Set タグの使用法の詳細な説明 MyBatis は、豊富な動的 SQL タグを提供し、データベース操作ステートメントを柔軟に構築できる優れた永続層フレームワークです。このうち、Set タグは、UPDATE ステートメントで SET 句を生成するために使用され、更新操作でよく使用されます。この記事では、MyBatis での Set タグの使用法を詳細に説明し、特定のコード例を通じてその機能を示します。 SetタグとはMyBatiで使用するSetタグです。

SQL の ID 属性は何を意味しますか? SQL の ID 属性は何を意味しますか? Feb 19, 2024 am 11:24 AM

SQL における Identity とは何ですか? 具体的なコード例が必要です。SQL では、Identity は自動インクリメント数値の生成に使用される特別なデータ型です。多くの場合、テーブル内のデータの各行を一意に識別するために使用されます。 Identity 列は、各レコードが一意の識別子を持つようにするために、主キー列と組み合わせてよく使用されます。この記事では、Identity の使用方法といくつかの実用的なコード例について詳しく説明します。 Identity の基本的な使用方法は、テーブルを作成するときに Identity を使用することです。

Windows サーバーのバックアップをインストール、アンインストール、リセットする方法 Windows サーバーのバックアップをインストール、アンインストール、リセットする方法 Mar 06, 2024 am 10:37 AM

WindowsServerBackup は、WindowsServer オペレーティング システムに付属する機能で、ユーザーが重要なデータとシステム構成を保護し、中小企業、エンタープライズ レベルの企業に完全なバックアップおよび回復ソリューションを提供できるように設計されています。この機能を使用できるのは、Server2022 以降を実行しているユーザーのみです。この記事では、WindowsServerBackup のインストール、アンインストール、またはリセットの方法を説明します。 Windows Server バックアップをリセットする方法 サーバー バックアップで問題が発生したり、バックアップに時間がかかりすぎたり、保存されているファイルにアクセスできない場合は、Windows Server バックアップ設定をリセットすることを検討してください。 Windowsをリセットするには

SQL の 5120 エラーを解決する方法 SQL の 5120 エラーを解決する方法 Mar 06, 2024 pm 04:33 PM

解決策: 1. ログインしているユーザーがデータベースにアクセスまたは操作するための十分な権限を持っているかどうかを確認し、ユーザーが正しい権限を持っているかどうかを確認します; 2. SQL Server サービスのアカウントに指定されたファイルまたはデータベースにアクセスする権限があるかどうかを確認します。 3. 指定されたデータベース ファイルが他のプロセスによって開かれているかロックされているかどうかを確認し、ファイルを閉じるか解放して、クエリを再実行します。管理者として試してください。Management Studio をなどとして実行します。

SQL ステートメントを使用せずに Springboot+Mybatis-plus を実装して複数のテーブルを追加する方法 SQL ステートメントを使用せずに Springboot+Mybatis-plus を実装して複数のテーブルを追加する方法 Jun 02, 2023 am 11:07 AM

Springboot+Mybatis-plus が SQL ステートメントを使用して複数テーブルの追加操作を実行しない場合、私が遭遇した問題は、テスト環境で思考をシミュレートすることによって分解されます: パラメーターを含む BrandDTO オブジェクトを作成し、パラメーターをバックグラウンドに渡すことをシミュレートします。 Mybatis-plus で複数テーブルの操作を実行するのは非常に難しいことを理解してください。Mybatis-plus-join などのツールを使用しない場合は、対応する Mapper.xml ファイルを設定し、臭くて長い ResultMap を設定するだけです。対応する SQL ステートメントを記述します。この方法は面倒に見えますが、柔軟性が高く、次のことが可能です。

See all articles