Heim Datenbank MySQL-Tutorial Auditing SQL Server SQL Statements

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

这里写图片描述

这里一个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>
Nach dem Login kopieren

这里写图片描述

这里有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>
Nach dem Login kopieren

这里写图片描述
上面这段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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

这里写图片描述
正是如此 !综上所述, 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>
Nach dem Login kopieren

这里写图片描述
这儿多了个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>
Nach dem Login kopieren

这里写图片描述
并没有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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

从结果集我们可以看到,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>
Nach dem Login kopieren

我们在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>
Nach dem Login kopieren
<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>
Nach dem Login kopieren
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Was ist der Unterschied zwischen HQL und SQL im Hibernate-Framework? Was ist der Unterschied zwischen HQL und SQL im Hibernate-Framework? Apr 17, 2024 pm 02:57 PM

HQL und SQL werden im Hibernate-Framework verglichen: HQL (1. Objektorientierte Syntax, 2. Datenbankunabhängige Abfragen, 3. Typsicherheit), während SQL die Datenbank direkt betreibt (1. Datenbankunabhängige Standards, 2. Komplexe ausführbare Datei). Abfragen und Datenmanipulation).

Verwendung der Divisionsoperation in Oracle SQL Verwendung der Divisionsoperation in Oracle SQL Mar 10, 2024 pm 03:06 PM

„Verwendung der Divisionsoperation in OracleSQL“ In OracleSQL ist die Divisionsoperation eine der häufigsten mathematischen Operationen. Während der Datenabfrage und -verarbeitung können uns Divisionsoperationen dabei helfen, das Verhältnis zwischen Feldern zu berechnen oder die logische Beziehung zwischen bestimmten Werten abzuleiten. In diesem Artikel wird die Verwendung der Divisionsoperation in OracleSQL vorgestellt und spezifische Codebeispiele bereitgestellt. 1. Zwei Arten von Divisionsoperationen in OracleSQL In OracleSQL können Divisionsoperationen auf zwei verschiedene Arten durchgeführt werden.

Vergleich und Unterschiede der SQL-Syntax zwischen Oracle und DB2 Vergleich und Unterschiede der SQL-Syntax zwischen Oracle und DB2 Mar 11, 2024 pm 12:09 PM

Oracle und DB2 sind zwei häufig verwendete relationale Datenbankverwaltungssysteme, die jeweils über ihre eigene, einzigartige SQL-Syntax und -Eigenschaften verfügen. In diesem Artikel werden die SQL-Syntax von Oracle und DB2 verglichen und unterschieden und spezifische Codebeispiele bereitgestellt. Datenbankverbindung Verwenden Sie in Oracle die folgende Anweisung, um eine Verbindung zur Datenbank herzustellen: CONNECTusername/password@database. In DB2 lautet die Anweisung zum Herstellen einer Verbindung zur Datenbank wie folgt: CONNECTTOdataba

Ausführliche Erläuterung der Funktion „Tag festlegen' in den dynamischen SQL-Tags von MyBatis Ausführliche Erläuterung der Funktion „Tag festlegen' in den dynamischen SQL-Tags von MyBatis Feb 26, 2024 pm 07:48 PM

Interpretation der dynamischen SQL-Tags von MyBatis: Detaillierte Erläuterung der Verwendung von Set-Tags. MyBatis ist ein hervorragendes Persistenzschicht-Framework. Es bietet eine Fülle dynamischer SQL-Tags und kann Datenbankoperationsanweisungen flexibel erstellen. Unter anderem wird das Set-Tag zum Generieren der SET-Klausel in der UPDATE-Anweisung verwendet, die sehr häufig bei Aktualisierungsvorgängen verwendet wird. In diesem Artikel wird die Verwendung des Set-Tags in MyBatis ausführlich erläutert und seine Funktionalität anhand spezifischer Codebeispiele demonstriert. Was ist Set-Tag? Set-Tag wird in MyBati verwendet

Was bedeutet das Identitätsattribut in SQL? Was bedeutet das Identitätsattribut in SQL? Feb 19, 2024 am 11:24 AM

Was ist Identität in SQL? In SQL ist Identität ein spezieller Datentyp, der zum Generieren automatisch inkrementierender Zahlen verwendet wird. Er wird häufig verwendet, um jede Datenzeile in einer Tabelle eindeutig zu identifizieren. Die Spalte „Identität“ wird oft in Verbindung mit der Primärschlüsselspalte verwendet, um sicherzustellen, dass jeder Datensatz eine eindeutige Kennung hat. In diesem Artikel wird die Verwendung von Identity detailliert beschrieben und es werden einige praktische Codebeispiele aufgeführt. Die grundlegende Möglichkeit, Identity zu verwenden, besteht darin, Identit beim Erstellen einer Tabelle zu verwenden.

Anleitung zum Installieren, Deinstallieren und Zurücksetzen des Windows-Server-Backups Anleitung zum Installieren, Deinstallieren und Zurücksetzen des Windows-Server-Backups Mar 06, 2024 am 10:37 AM

WindowsServerBackup ist eine Funktion des WindowsServer-Betriebssystems, die Benutzern dabei helfen soll, wichtige Daten und Systemkonfigurationen zu schützen und vollständige Sicherungs- und Wiederherstellungslösungen für kleine, mittlere und große Unternehmen bereitzustellen. Nur Benutzer, die Server2022 und höher ausführen, können diese Funktion nutzen. In diesem Artikel erklären wir, wie Sie WindowsServerBackup installieren, deinstallieren oder zurücksetzen. So setzen Sie die Windows Server-Sicherung zurück: Wenn Sie Probleme mit der Sicherung Ihres Servers haben, die Sicherung zu lange dauert oder Sie nicht auf gespeicherte Dateien zugreifen können, können Sie die Sicherungseinstellungen Ihres Windows Servers zurücksetzen. Um Windows zurückzusetzen

So beheben Sie den 5120-Fehler in SQL So beheben Sie den 5120-Fehler in SQL Mar 06, 2024 pm 04:33 PM

Lösung: 1. Überprüfen Sie, ob der angemeldete Benutzer über ausreichende Berechtigungen zum Zugriff auf oder zum Betrieb der Datenbank verfügt, und stellen Sie sicher, dass der Benutzer über die richtigen Berechtigungen verfügt. 2. Überprüfen Sie, ob das Konto des SQL Server-Dienstes über die Berechtigung zum Zugriff auf die angegebene Datei verfügt Ordner und stellen Sie sicher, dass das Konto über ausreichende Berechtigungen zum Lesen und Schreiben der Datei oder des Ordners verfügt. 3. Überprüfen Sie, ob die angegebene Datenbankdatei von anderen Prozessen geöffnet oder gesperrt wurde. Versuchen Sie, die Datei zu schließen oder freizugeben, und führen Sie die Abfrage erneut aus . Versuchen Sie es als Administrator. Führen Sie Management Studio aus als usw.

So implementieren Sie Springboot+Mybatis-plus, ohne SQL-Anweisungen zum Hinzufügen mehrerer Tabellen zu verwenden So implementieren Sie Springboot+Mybatis-plus, ohne SQL-Anweisungen zum Hinzufügen mehrerer Tabellen zu verwenden Jun 02, 2023 am 11:07 AM

Wenn Springboot + Mybatis-plus keine SQL-Anweisungen zum Hinzufügen mehrerer Tabellen verwendet, werden die Probleme, auf die ich gestoßen bin, durch die Simulation des Denkens in der Testumgebung zerlegt: Erstellen Sie ein BrandDTO-Objekt mit Parametern, um die Übergabe von Parametern an den Hintergrund zu simulieren dass es äußerst schwierig ist, Multi-Table-Operationen in Mybatis-plus durchzuführen. Wenn Sie keine Tools wie Mybatis-plus-join verwenden, können Sie nur die entsprechende Mapper.xml-Datei konfigurieren und die stinkende und lange ResultMap konfigurieren Schreiben Sie die entsprechende SQL-Anweisung. Obwohl diese Methode umständlich erscheint, ist sie äußerst flexibel und ermöglicht es uns

See all articles