探索SQL Server元資料(二)
背景
上一篇中,我介紹了SQL Server 允許訪問資料庫的元資料,為什麼有元資料,如何使用元資料。這一篇中我會介紹如何進一步找到各種有價值的資訊。以觸發器為例,因為它們往往一起很多問題。
那麼如何找到觸發器的資料?
以sys.system_viewsis表開始。讓我們查詢出資料庫中使用觸發器的資訊。可以告知你當前SQL Server版本中有什麼觸發器。
SELECT schema_name(schema_ID)+'.'+ name FROM sys.system_views WHERE name LIKE '%trigger%'
---------------------------------------- sys.dm_exec_trigger_stats sys.server_trigger_events sys.server_triggers sys.trigger_event_types sys.trigger_events sys.triggers (6 row(s) affected)
其中sys.triggers看起來資訊很多,它又包含什麼列?下面這個查詢很容易查到:
SELECT Thecol.name+ ' '+ Type_name(TheCol.system_type_id) + CASE WHEN TheCol.is_nullable=1 THEN ' NULL' ELSE ' NOT NULL' END as Column_Information FROM sys.system_views AS TheView INNER JOIN sys.system_columns AS TheCol ON TheView.object_ID=TheCol.Object_ID WHERE TheView.name = 'triggers' ORDER BY column_ID;
結果如下:
Column_Information ---------------------------------------- name nvarchar NOT NULL object_id int NOT NULL parent_class tinyint NOT NULL parent_class_desc nvarchar NULL parent_id int NOT NULL type char NOT NULL type_desc nvarchar NULL create_date datetime NOT NULL modify_date datetime NOT NULL is_ms_shipped bit NOT NULL is_disabled bit NOT NULL is_not_for_replication bit NOT NULL is_instead_of_trigger bit NOT NULL
因此我們多這個資訊有了更好的理解,有了一個目錄的目錄。這個概念有點讓人頭暈,但是另一方面,它也是相當簡單的。我們能夠查出元資料,再找個查詢中,需要做的就是改變這個單詞‘triggers’來查詢你想要的檢視名稱。.
在2012及其以後版本,可以使用一個新的表值函式極大地簡化上述查詢,並可以避免各種連線。在下面的查詢中,我們將查詢sys.triggers 檢視 中的列。可以使用相同的查詢通過更改字串中的物件名稱來獲取任何檢視的定義。
SELECT name+ ' '+ system_type_name + CASE WHEN is_nullable=1 THEN ' NULL' ELSE ' NOT NULL' END as Column_Information FROM sys.dm_exec_describe_first_result_set ( N'SELECT * FROM sys.triggers;', NULL, 0) AS f ORDER BY column_ordinal;
查詢結果如下:
Column_Information ---------------------------------------- name nvarchar(128) NOT NULL object_id int NOT NULL parent_class tinyint NOT NULL parent_class_desc nvarchar(60) NULL parent_id int NOT NULL type char(2) NOT NULL type_desc nvarchar(60) NULL create_date datetime NOT NULL modify_date datetime NOT NULL is_ms_shipped bit NOT NULL is_disabled bit NOT NULL is_not_for_replication bit NOT NULL is_instead_of_trigger bit NOT NULL
sys.dm_exec_describe_first_result_set函式的最大優勢在於你能看到任何結果的列,不僅僅是表和檢視、儲存過程或者貶值函式。
為了查出任何列的資訊,你可以使用稍微修改的版本,只需要改變程式碼中的字串'sys.triggers'即可,如下:
Declare @TheParamater nvarchar(255) Select @TheParamater = 'sys.triggers' Select @TheParamater = 'SELECT * FROM ' + @TheParamater SELECT name+ ' '+ system_type_name + CASE WHEN is_nullable=1 THEN ' NULL' ELSE ' NOT NULL' END as Column_Information FROM sys.dm_exec_describe_first_result_set ( @TheParamater, NULL, 0) AS f ORDER BY column_ordinal;
但是當然一個觸發器是首先是一個物件,因此一定在sys.objects?
在我們使用sys.triggers的資訊之前,需要來重複一遍,所有的資料庫物件都存在於sys.objects中,在SQL Server 中的物件包括以下:聚合的CLR函式,check 約束,SQL標量函式,CLR標量函式,CLR表值函式,SQL內聯表值函式,內部表,SQL儲存過程,CLR儲存過程,計劃指南,主鍵約束,老式規則,複製過濾程式,系統基礎表,同義詞,序列物件,服務佇列,CLR DML 觸發器,SQL表值函式,表型別,使用者自定義表,唯一約束,檢視和擴充套件儲存過程等。
觸發器是物件所以基礎資訊一定儲存在sys.objects。不走運的是,有時我們需要額外的資訊,這些資訊可以通過目錄檢視查詢。這些額外資料有是什麼呢?
修改我們使用過的查詢,來查詢sys.triggers的列,這次我們會看到額外資訊。這些額外列是來自於sys.objects。
SELECT coalesce(trigger_column.name,'NOT INCLUDED') AS In_Sys_Triggers, coalesce(object_column.name,'NOT INCLUDED') AS In_Sys_Objects FROM (SELECT Thecol.name FROM sys.system_views AS TheView INNER JOIN sys.system_columns AS TheCol ON TheView.object_ID=TheCol.Object_ID WHERE TheView.name = 'triggers') trigger_column FULL OUTER JOIN (SELECT Thecol.name FROM sys.system_views AS TheView INNER JOIN sys.system_columns AS TheCol ON TheView.object_ID=TheCol.Object_ID WHERE TheView.name = 'objects') object_column ON trigger_column.name=object_column.name 查詢結果: In_Sys_Triggers In_Sys_Objects ------------------------------ ---------------------- name name object_id object_id NOT INCLUDED principal_id NOT INCLUDED schema_id NOT INCLUDED parent_object_id type type type_desc type_desc create_date create_date modify_date modify_date is_ms_shipped is_ms_shipped NOT INCLUDED is_published NOT INCLUDED is_schema_published is_not_for_replication NOT INCLUDED is_instead_of_trigger NOT INCLUDED parent_id NOT INCLUDED is_disabled NOT INCLUDED parent_class NOT INCLUDED parent_class_desc NOT INCLUDED
以上這些讓我們知道在sys.triggers的額外資訊,但是因為它始終是表的子物件,所以有些不相關資訊是不會展示在這些指定的檢視或者sys.triggers中的。現在就要帶大家去繼續找找這些資訊。
觸發器的問題
觸發器是有用的,但是因為它們在SSMS物件資源管理器窗格中不是可見的,所以一般用來提醒錯誤。觸發器有時候會有些微妙的地方讓其出問題,比如,當匯入過程中禁用了觸發器,並且由於某些原因他們沒有重啟。
下面是一個關於觸發器的簡要提醒:
觸發器可以在檢視,表或者伺服器上,任何這些物件上都可以有超過1個觸發器。普通的DML觸發器能被定義來執行替代一些資料修改(Insert,Update或者Delete)或者在資料修改之後執行。每一個觸發器與只與一個物件管理。DDL觸發器與資料庫關聯或者被定義在伺服器級別,這類觸發器一般在Create,Alter或者Drop這類SQL語句執行後觸發。
像DML觸發器一樣,可以有多個DDL觸發器被建立在同一個T-SQL語句上。一個DDL觸發器和語句觸發它的語句在同一個事務中執行,所以除了Alter DATABASE之外都可以被回滾。DDL觸發器執行在T-SQL語句執行完畢後,也就是不能作為Instead OF觸發器使用。
兩種觸發器都與事件相關,在DML觸發器中,包含INSERT, UPDATE, 和DELETE,然而很多事件都可以與DDL觸發器關聯,稍後我們將瞭解。
在資料庫中列出觸發器
那麼怎麼獲取觸發器列表?下面我在AdventureWorks資料庫中進行查詢,注意該庫的檢視中沒有觸發器。
第一個查詢所有資訊都在sys.triggers 的目錄檢視中。
SELECT name AS TriggerName, coalesce(object_schema_name(parent_ID)+'.' +object_name(parent_ID),'Database ('+db_name()+')') AS TheParent FROM sys.triggers; TriggerName TheParent ------------------------------ ---------------------------------------- ddlDatabaseTriggerLog Database (AdventureWorks2012) dEmployee HumanResources.Employee iuPerson Person.Person iPurchaseOrderDetail Purchasing.PurchaseOrderDetail uPurchaseOrderDetail Purchasing.PurchaseOrderDetail uPurchaseOrderHeader Purchasing.PurchaseOrderHeader iduSalesOrderDetail Sales.SalesOrderDetail uSalesOrderHeader Sales.SalesOrderHeader dVendor Purchasing.Vendor iWorkOrder Production.WorkOrder uWorkOrder Production.WorkOrder
我使用元資料函式db_name()使SQL保持簡單。db_name()告訴我資料庫的名稱。object_schema_name()用來查詢object_ID代表的物件的架構,以及object_name()查詢物件名稱。這些對物件的引用指向觸發器的所有者,觸發器可以是資料庫本身,也可以是表:伺服器觸發器有自己的系統檢視,稍後我會展示。
如果想要看到所有觸發器,那麼我們最好使用sys.objects 檢視:
SELECT name as TriggerName, object_schema_name(parent_object_ID)+'.' +object_name(parent_object_ID) AS TheParent FROM sys.objects WHERE OBJECTPROPERTYEX(object_id,'IsTrigger') = 1
注意,輸出不包含資料庫級別的觸發器,因為所有的DML觸發器都在sys.objects檢視中,但是你會漏掉在sys.triggers檢視中的觸發器。
上面查詢結果:
name TheParent ------------------------------ ------------------------------- dEmployee HumanResources.Employee iuPerson Person.Person iPurchaseOrderDetail Purchasing.PurchaseOrderDetail uPurchaseOrderDetail Purchasing.PurchaseOrderDetail uPurchaseOrderHeader Purchasing.PurchaseOrderHeader iduSalesOrderDetail Sales.SalesOrderDetail uSalesOrderHeader Sales.SalesOrderHeader dVendor Purchasing.Vendor iWorkOrder Production.WorkOrder uWorkOrder Production.WorkOrder
我的表和檢視有多少個觸發器?
我想知道每個表有多少個觸發器,並且什麼情況下觸發它們。下面我們列出了具有觸發器的表以及每個事件的觸發器數量。每個表或者檢視對於觸發器行為都有一個INSTEAD OF 觸發器,可能是UPDATE, DELETE, 或者 INSERT
。但是一個表可以有多個AFTER觸發器行為。這些將展示在下面的查詢中(排除檢視):
SELECT convert(CHAR(32),coalesce(object_schema_name(parent_ID)+'.' +object_name(parent_ID),'Database ('+db_name()+')')) AS 'Table', triggers,[KD1] [AC2] convert(SMALLINT,objectpropertyex(parent_ID, N'TABLEDeleteTriggerCount')) AS 'Delete', convert(SMALLINT,objectpropertyex(parent_ID, N'TABLEInsertTriggerCount')) AS 'Insert', convert(SMALLINT,objectpropertyex(parent_ID, N'TABLEUpdateTriggerCount')) AS 'Update' FROM (SELECT count(*) AS triggers, parent_ID FROM sys.triggers WHERE objectpropertyex(parent_ID, N'IsTable') =1 GROUP BY parent_ID )TablesOnly; --查詢結果如下: Table triggers Delete Insert Update -------------------------------- ----------- ------ ------ ------ Purchasing.Vendor 1 0 0 0 Production.WorkOrder 2 0 1 1 Purchasing.PurchaseOrderDetail 2 0 1 1 Purchasing.PurchaseOrderHeader 1 0 0 1 Sales.SalesOrderDetail 1 1 1 1 HumanResources.Employee 1 0 0 0 Sales.SalesOrderHeader 1 0 0 1 Person.Person 1 0 1 1 (8 row(s) affected)
如果超過一個觸發器被觸發在一個表上,它們不保證順序,當然也可以使用sp_settriggerorder來控制順序。通過使用objectpropertyex()元資料函式,需要根據事件輸入引數‘ExecIsLastDeleteTrigger’, ‘ExecIsLastInsertTrigger’ 或者 ‘ExecIsLastUpdateTrigger’來確認誰是最後一個執行的觸發器 。為了得到第一個觸發器,酌情使用ObjectPropertyEx() 元資料函式,需要輸入引數 ‘ExecIsFirstDeleteTrigger’, ‘ExecIsFirstInsertTrigger’ 或者 ‘ExecIsFirstUpdateTrigger’。
因此我們現在知道了表有哪些觸發器,哪些事件觸發這些觸發器。可以使用objectpropertyex()元資料函式,這個函式返回很多不同資訊,根據指定的引數不同。通過檢視MSDN中的文件,檢視其中的一個文件是否有助於元資料查詢,總是值得檢查的。
觸發器何時觸發事件?
讓我們看一下這些觸發器,DML觸發器可以在所有其他時間發生後觸發,但是可以在約束被處理前並且觸發INSTEAD OF觸發動作。下面我們就來看看所有的觸發的到底是AFTER 還是INSTEAD OF 觸發器,有事什麼時間觸發了觸發器。
/* 列出觸發器,無論它們是否啟用,以及觸發器事件。*/ SELECT convert(CHAR(25),name) AS triggerName, convert(CHAR(32),coalesce(object_schema_name(parent_ID)+'.' +object_name(parent_ID),'Database ('+db_name()+')')) AS TheParent, is_disabled, CASE WHEN is_instead_of_trigger=1 THEN 'INSTEAD OF ' ELSE 'AFTER ' END +Stuff (--get a list of events for each trigger (SELECT ', '+type_desc FROM sys.trigger_events te WHERE te.object_ID=sys.triggers.object_ID FOR XML PATH(''), TYPE).value('.', 'varchar(max)'),1,2,'') AS events FROM sys.triggers;
結果如下:
triggerName TheParent is_disabled events ------------------------- -------------------------------- ----------- --------- ddlDatabaseTriggerLog Database (AdventureWorks2012) 1 AFTER CREATE_TABLE, ALTER_TABLE, DROP_TABLE, CREATE_VIEW, ALTER_VIEW, DROP_VIEW, CREATE_INDEX, ALTER_INDEX, DROP_INDEX, CREATE_XML_INDEX, ALTER_FULLTEXT_INDEX, CREATE_FULLTEXT_INDEX, DROP_FULLTEXT_INDEX, CREATE_SPATIAL_INDEX, CREATE_STATISTICS, UPDATE_STAT t_AB dbo.AB 0 INSTEAD OF INSERT dEmployee HumanResources.Employee 0 INSTEAD OF DELETE iuPerson Person.Person 0 AFTER INSERT, UPDATE iPurchaseOrderDetail Purchasing.PurchaseOrderDetail 0 AFTER INSERT uPurchaseOrderDetail Purchasing.PurchaseOrderDetail 0 AFTER UPDATE uPurchaseOrderHeader Purchasing.PurchaseOrderHeader 0 AFTER UPDATE iduSalesOrderDetail Sales.SalesOrderDetail 0 AFTER INSERT, UPDATE, DELETE uSalesOrderHeader Sales.SalesOrderHeader 0 AFTER UPDATE dVendor Purchasing.Vendor 0 INSTEAD OF DELETE iWorkOrder Production.WorkOrder 0 AFTER INSERT uWorkOrder Production.WorkOrder 0 AFTER UPDATE
As you will notice, we used a FOR XML PATH(‘’) trick here to make a list of the events for each trigger to make it easier to read. These events were pulled from the sys.trigger_events view using a correlated subquery.
注意到我們使用了FOR XML PATH(‘’) 來列出事件的每一個觸發器,更容易讀取理解。sys.trigger_events使用相關子查詢來查詢這些事件。
觸發器的多長?
許多資料庫人員不贊成冗長觸發器的定義,但他們可能會發現,根據定義的長度排序的觸發器列表是研究資料庫的一種有用方法。
SELECT convert(CHAR(32),coalesce(object_schema_name(t.object_ID)+'.','') +name) AS TheTrigger, convert(CHAR(32),coalesce(object_schema_name(parent_ID)+'.' +object_name(parent_ID),'Database ('+db_name()+')')) AS theParent, len(definition) AS length --the length of the definition FROM sys.SQL_modules m INNER JOIN sys.triggers t ON t.object_ID=m.object_ID ORDER BY length DESC;
訪問sys.SQL_modules檢視可以檢視觸發器定義的SQL DDL,並按大小順序列出它們,最上面是最大的。
結果:
TheTrigger theParent length -------------------------------- -------------------------------- -------- Sales.iduSalesOrderDetail Sales.SalesOrderDetail 3666 Sales.uSalesOrderHeader Sales.SalesOrderHeader 2907 Purchasing.uPurchaseOrderDetail Purchasing.PurchaseOrderDetail 2657 Purchasing.iPurchaseOrderDetail Purchasing.PurchaseOrderDetail 1967 Person.iuPerson Person.Person 1498 ddlDatabaseTriggerLog Database (AdventureWorks2012) 1235 Purchasing.dVendor Purchasing.Vendor 1103 Production.uWorkOrder Production.WorkOrder 1103 Purchasing.uPurchaseOrderHeader Purchasing.PurchaseOrderHeader 1085 Production.iWorkOrder Production.WorkOrder 1011 HumanResources.dEmployee HumanResources.Employee 604
好吧,我可能太挑剔了,不太喜歡太長的,但是邏輯有時候會很長。事實上,前三名在我看來是不可靠的,儘管我總是傾向於儘可能少地使用觸發器。
這些觸發器訪問了多少物件
在程式碼中,每個觸發器要訪問多少物件(比如表和函式)?
我們只需要檢查表示式依賴項。這個查詢使用一個檢視來列出“軟”依賴項(如觸發器、檢視和函式)。
SELECT coalesce(object_schema_name(parent_id) +'.','')+convert(CHAR(32),name) AS TheTrigger, count(*) AS Dependencies FROM sys.triggers INNER JOIN sys.SQL_Expression_dependencies ON [referencing_id]=object_ID GROUP BY name, parent_id ORDER BY count(*) DESC; --結果: TheTrigger Dependencies ---------------------------------------- ------------ Sales.iduSalesOrderDetail 7 Sales.uSalesOrderHeader 7 Purchasing.iPurchaseOrderDetail 5 Purchasing.uPurchaseOrderDetail 5 Purchasing.uPurchaseOrderHeader 3 Production.iWorkOrder 3 Production.uWorkOrder 3 dbo.t_AB 2 Purchasing.dVendor 2 Person.iuPerson 2 ddlDatabaseTriggerLog 1
居然有兩個觸發器有7個依賴!讓我們就Sales.iduSalesOrderDetail來實際看一下,有哪些依賴。
特定觸發器訪問或者寫入哪些物件?
我們可以列出觸發器在程式碼中引用的所有物件
SELECT convert(char(32),name) as TheTrigger, convert(char(32),coalesce([referenced_server_name]+'.','') +coalesce([referenced_database_name]+'.','') +coalesce([referenced_schema_name]+'.','')+[referenced_entity_name]) as referencedObject FROM sys.triggers INNER JOIN sys.SQL_Expression_dependencies ON [referencing_id]=object_ID WHERE name LIKE 'iduSalesOrderDetail'; --查詢結果: TheTrigger referencedObject -------------------------------- -------------------------------- iduSalesOrderDetail Sales.Customer iduSalesOrderDetail Person.Person iduSalesOrderDetail Sales.SalesOrderDetail iduSalesOrderDetail Sales.SalesOrderHeader iduSalesOrderDetail Production.TransactionHistory iduSalesOrderDetail dbo.uspLogError iduSalesOrderDetail dbo.uspPrintError
觸發器裡有什麼程式碼?
現在讓我們通過檢查觸發器的原始碼來確認這一點。.
SELECT OBJECT_DEFINITION ( object_id('sales.iduSalesOrderDetail') );
我們之前的查詢是正確的,掃描原始碼可知所有的依賴項。大量依賴項表名對於資料庫的重構等需要非常小心,例如,修改一個基礎表的列。
據需要做什麼,您可能希望檢查來自元資料檢視的定義,而不是使用OBJECT_DEFINITION函式。
SELECT definition FROM sys.SQL_modules m INNER JOIN sys.triggers t ON t.object_ID=m.object_ID WHERE t.object_ID=object_id('sales.iduSalesOrderDetail');
搜尋觸發器的程式碼
There are always plenty of ways of using the metadata views and functions. I wonder if all these triggers are executing that uspPrintError procedure?
有很多使用元資料檢視和函式的方法。想知道是否所有這些觸發器都執行uspPrintError儲存過程?
/* 在所有觸發器中搜索字串 */
SELECT convert(CHAR(32),coalesce(object_schema_name(object_ID)+'.','') +name) AS TheTrigger, '...'+substring(definition, hit-20,120) +'...' FROM (SELECT name, definition, t.object_ID, charindex('EXECUTE [dbo].[uspPrintError]',definition) AS hit FROM sys.SQL_modules m INNER JOIN sys.triggers t ON t.object_ID=m.object_ID)f WHERE hit>0;
結果如圖:
8個引用正在執行這個過程。我們在sys.SQL_modules中搜索了所有的定義可以找到一個特定的字串,這種方式很慢很暴力,但是它是有效的!
在所有物件中搜索字串
我想知道除了觸發器之外是否還有其他物件呼叫這個過程?我們稍微修改查詢以搜尋sys.objects檢視,而不是sys.triggers,以搜尋所有具有與之關聯的程式碼的物件。我們還需要顯示物件的型別
/* 在所有物件中搜索字串 */
SELECT convert(CHAR(32),coalesce(object_schema_name(object_ID)+'.','') +object_name(object_ID)) AS TheObject, type_desc, '...'+substring(definition,hit-20,120)+'...' as TheExtract FROM (SELECT type_desc, definition, o.object_ID, charindex('uspPrintError',definition) AS hit FROM sys.SQL_modules m INNER JOIN sys.objects o ON o.object_ID=m.object_ID)f WHERE hit>0;
查詢結果如下圖:
From this output we can see that, other than the procedure itself where it is defined, and the triggers, only dbo.uspLogError is executing the uspPrintError procedure. (see the first column, second line down)
從這個輸出中我們可以看到,除了在定義它的過程本身之外,還有觸發器,只有dbo.uspLogError正在執行uspPrintError過程。(見第一列,第二行往下)
列出伺服器級觸發器及其定義
我們可以通過系統檢視瞭解它們嗎?嗯,是的。以下是列出伺服器觸發器及其定義的語句
SELECT name, definition
FROM sys.server_SQL_modules m
INNER JOIN sys.server_triggers t
ON t.object_ID=m.object_ID;
注意,只能看到有許可權看的觸發器
總結
本文討論過觸發器,並且你能查出觸發器,以及潛在的問題。這裡並沒有針對關於觸發器的查詢提供一個全面的工具箱,因為我只是使用觸發器作為示例來展示在查詢系統檢視時可能使用的一些技術。在我們學習了索引、列和引數之後,我們將回到觸發器,並瞭解了編寫訪問系統檢視和information schema檢視的查詢的一些日常用途。表是元資料的許多方面的基礎。它們是幾種型別的物件的父類,其他元資料如索引是表的屬性。我們正在慢慢地努力去發現所有關於表的資訊。期待下期
相關推薦
探索SQL Server元資料(二)
背景 上一篇中,我介紹了SQL Server 允許訪問資料庫的元資料,為什麼有元資料,如何使用元資料。這一篇中我會介紹如何進一步找到各種有價值的資訊。以觸發器為例,因為它們往往一起很多問題。 那麼如何找到觸發器的資料? 以sys.system_viewsis表開始。讓我們查詢出資料庫中使用觸發器的資
探索SQL Server元資料(一)
簡介 在資料庫中,我們除了儲存資料外,還儲存了大量的元資料。它們主要的作用就是描述資料庫怎麼建立、配置、以及各種物件的屬性等。本篇簡單介紹如何使用和查詢元資料,如何更有效的管理SQLServer 資料庫。 對一些有經驗的資料庫開發和管理人員而言,元資料是非常有價值的。下面我會介紹一下簡單的原理,然後
探索SQL Server元資料(三):索引元資料
背景 在第一篇中我介紹瞭如何訪問元資料,元資料為什麼在資料庫裡面,以及如何使用元資料。介紹瞭如何查出各種資料庫物件的在資料庫裡面的名字。第二篇,我選擇了觸發器的主題,因為它是一個能提供很好例子的資料庫物件,並且在這個物件中能夠提出問題和解決問題。 本篇我將會介紹元資料中的索引,不僅僅是因為它們本身很重要,更
SQL Server 安全篇——安全元資料(5)——元資料自身安全性
隨著元資料的使用頻率越來越高,安全性也越來越凸顯,因為從元資料中可以得到很多不應該隨意暴露的系統資訊。所以,絕大部分的元資料並不能隨意被檢視,通常都需要授權。 比如當一個使用者A被授權查詢B表,那麼這個使用者A就自動獲得了在sys.tables和sys.obje
SQL Server 安全篇——安全元資料(3)——稽核元資料
稽核除了應對使用者行為之外,還能進行“稽核稽核”以避免別人對自己的懷疑。比如一個惡意的 DBA關閉了稽核, 然後執行的是一個危險的行為, 則該操作本身將不會被稽核, 但 由於DBA已經關閉了審計,
Exchange Server 2013 部署(二)部署&常規配置命令[一]
Exchange 2013 部署 ExchangeServer 2013 Exchange部署 命令設置Exchange 在Exchange Server 2013 先決條件滿足後,進行Exchange Server 2013 部署及配置。1.掛載Exchange Server 2013 鏡像
Exchange Server 2013 部署(二)部署&常規配置命令[二]
Exchange 2013配置 Exchange PowerShell Exchange 2013 部署 Exchange 2013基本配置 繼續使用命令設置Exchange Server 2013 的常規配置。1.使用命令創建證書請求文件New-ExchangeCertificate -Ge
SQL一般註入(二)
current csrf 註入 ascii ati cookie ble true () mysql一般註入(二) 1.mysql一般註入(insert、update) mysql一般請求mysql_query不支持多語句執行,mysqli可以。 inse
SQL Server進階(一)T-SQL查詢和編程的背景
.com src 編程 server 分享 bubuko 進階 分享圖片 img SQL Server進階(一)T-SQL查詢和編程的背景
SQL Server進階(六)表表達式
ins upd 逗號 csdn 引用 ssd 優點 暫存 可讀性 概述 SQL Server支持四種類型的表表達式:派生表,公用表表達式,視圖和內聯表值函數。 派生表 派生表是一個查詢結果生成的表,類似於臨時表。 派生表可以簡化查詢,避免使用臨時表。相比手動生成
SQL Server進階(七)集合運算
nbsp 分享圖片 src 函數 server -c 計算 lec 括號 概述 為什麽使用集合運算: 在集合運算中比聯接查詢和EXISTS/NOT EXISTS更方便。 並集運算(UNION) 並集:兩個集合的並集是一個包含集合A和B中所有元素的集合。
SQL Server進階(八)查詢
解決方案 查詢 小結 練習 數據 分組 函數 sql 方案 開窗函數 透視數據 逆透視數據 分組集 小結 練習 解決方案SQL Server進階(八)查詢
SQL Sever 資料庫視訊(二) 1024節日快樂!
分離資料庫: 其實就是將資料庫從SQL Server 2008的例項中分離出去,但是不會刪除該資料中的檔案和事務日誌檔案,這樣,資料庫就可以再附加到其他的 SQL Server 2008例項上去 (也可以理解成資料庫獨立出去,附加到別的例項上去)
使用Tensorflow來讀取訓練自己的資料(二)
接上一篇,繼續分析,model.py,也就是模型的構建。兩個卷積層,兩個池化層,以及後面的全連線層怎麼通過tensorflow定義的。 import tensorflow as tf def inference(images, batch_size, n_classess): # c
獲取表單資料(二)
<%@ page contentType="text/html;charset=gb2312"%> <%! public String codeToString(String str) {//處理中文字串的函式 String s=str;
C6748對EDMA的操作和通過EMIFA與FPGA傳輸資料(二)
/****************************************************************************/ /*
SQL Server On Linux(3)——SQL Server 2019 For Linux 下載並部署示例資料庫
接上文SQL Server On Linux(2)——SQL Server 2019 For Linux安裝過程細節研究 正所謂工欲善其事必先利其器,讀者可能也跟作者一樣很迫切希望瞭解和嘗試SQL Server On Linux及SQL 2019的各種新特性,不過為了走得
SQL Server On Linux(2)——SQL Server 2019 For Linux安裝過程細節研究
接上文SQL Server On Linux(1)——CentOS 7 安裝SQL Server2019 在安裝過程中,作者發現了一些資訊,這些資訊引起了作者的興趣,那麼下面作者把自己研究的結果分享出來,如果讀者對此有深入研究過,歡迎指正。 為什麼要研究這些東西?說白了就
SQL Server On Linux(1)——CentOS 7 安裝SQL Server2019
前言 SQL Server 2019已經正式公佈,雖然只是preview版,但是不影響我們追求新的技術。接下來的一個系列,隨著本人的研究,儘量讓這個系列成為“教程”,真正的入門到精通。 環境準備 不廢話,先把研究環境搭建起來。由於某些原因(晚點再說),本系列
SQL Server On Linux(4)——Linux 初步配置(1)
接上文:SQL Server On Linux(3)——SQL Server 2019 For Linux 下載並部署示例資料庫 本文聊一下Linux,因為這個系列是Linux上的SQL Server,所以我們有必要初步瞭解一下這個基石,地基不穩那麼上面搭建的東西也必然搖搖晃