星期五, 6月 29, 2012

[VFP] HighlightRowLineWidth:Expression evaluated to an illegal value

為方便使用者在 Grid 內可以較明顯看出整行資料,嘗試去設定 HighlineRowLineWidth,把它設為 10 後儲存離開 Form 後,只要一打開 Form 就會出現這個錯誤訊息,而且完全進不去 Form。

HighlightRowLineWidth:Expression evaluated to an illegal value 1

查詢 Help 才發現到 HighlightRowLineWidth 有效值是 0 至 7,預設值為 1,難怪會出問題。

VFP 的 Form 其實是一個 DBF,可以像開 DBF 資料庫一樣,直接用 USE 來開啟,利用 Command Windows 來進行修正參數
USE D:\Data.scx IN 0 SHARED
SET FILTER TO Objname = "grdOrderData" 
BROWSE
點選 Properties 欄位就會列出 grdOrderData 內全部 Property 設定值

HighlightRowLineWidth:Expression evaluated to an illegal value 2
修正 HighlineRowLineWidth 值就可以順利開啟這個 Form。

星期五, 6月 22, 2012

[Win] NT 4.0 上安裝 TCP/IP 通訊協定

把原本的 Windows Server 2000 淘汰掉,取而代之是 Windows Server 2008 R2,原是個簡單的移轉,畢竟是台資料量很少的 File Server,檔案 Copy 過去,並把 Client 端路徑換一換就行,沒想到工業機器電腦( Windows NT4.0)上沒有 TCP\IP(只有 NetBEUI),抓不到 2008 R2,更神奇地是我竟然無法在 NT4.0 上安裝 TCP\IP,都會出現下面訊息,錯誤訊息解讀為找不到檔案,無論利用 Browse 選擇路徑或是直接 Key 路徑,都是一樣的結果,後來發現 Browse 選擇路徑或是 key 路徑,竟然都指到 E 去,電腦認定光碟機在 E,可是明明就是在 D,最後把光碟機轉換成 E 後才順利把 TCP/IP 裝上去,結束這場鬧劇,Orz ~~

有想過要在 Windows Server 2008 R2 上安裝 NetBEUI 來解決問題,Google 後才發現 NetBEUI 在 XP 時就已經不支援,雖然可以利用光碟來安裝回去,但 R2 看來是沒有辦法這樣作。
TCPIP
公司內有兩台 NT4.0 電腦,另一台我一分鐘就裝好,完全沒有遇到任何困難, >.< ~~

星期五, 6月 15, 2012

[SQL] 特定符號隔離字串資料

Blog 中的每一篇文章,都可以設定多個關鍵字,常見型式為利用逗號(,)來串接每個關鍵字,EX:SQL,T-SQL,CTE,Split,此型式資料不容易拿來利用,因此需要把它正規化。

CHARINDEX() 函數說明

CHARINDEX ( expressionToFind ,expressionToSearch [ , start_location ] )語法
  1. expressionToFind 代表要在字串中尋找的目標(逗號)
  2. expressionToSearch 代表被搜尋字串(關鍵字)
  3. start_location 未指定、負數或 0,搜尋就會從 expressionToSearch 開頭開始,設定大於 0 的整數,代表這個字串位置開始往後搜尋
CTE 解法

DECLARE @Temp TABLE (PostTitle char(100),Keyword char(100))
INSERT INTO @Temp VALUES('[SQL] 模擬死結產生','SQL,DealLock')
INSERT INTO @Temp VALUES('[Windows] Win7 和 內碼輸入法','Windows 7,內碼,輸入法')
INSERT INTO @Temp VALUES('阿朗壹古道','CYMC,Hiking')
INSERT INTO @Temp VALUES('威力導演 9 - 直式相片模糊','威力導演,模糊,Video')
INSERT INTO @Temp VALUES('馬桶漏水','居家生活,馬桶,乾式安裝,漏水,HCG,和成')

;
WITH CTE AS
(
  SELECT 
    PostTitle , 
    Keyword ,
    1 AS StartPos , -- 錨點起點        
    CHARINDEX(',',Keyword) AS EndPos -- 錨點終點
  FROM @Temp
  UNION ALL 
  SELECT 
    PostTitle ,
    Keyword , 
    EndPos + 1 , -- 遞迴起點
    CHARINDEX(',',Keyword,EndPos + 1) -- 遞迴終點 
  FROM CTE
  WHERE EndPos > 0 -- CHARINDEX() 大於 0 表示還有逗號存在,遞迴繼續跑,等於 0 則遞迴停止
)
SELECT 
  PostTitle ,
  SUBSTRING
  (
    Keyword ,
    StartPos ,
    ISNULL -- 第一個參數假如為 NULL 就抓取第二參數來表示終點
      (
        NULLIF(EndPos,0) , -- 第一參數;利用 NULLIF() 把終點為 0 的值轉換成 NULL
        LEN(Keyword) + 1   -- 第二參數
      )
      - StartPos
  ) AS String
FROM CTE
ORDER BY 
  PostTitle , 
  StartPos -- 對起點進行排序,能確保關鍵字呈現順序

CTE 解法說明
 
CTE 錨點內設定 1 為錨點起點,關鍵字最左邊逗號為錨點終點,遞迴部分則是把終點 + 1 當成遞迴起點,利用指定 CHARINDEX() 第三個參數,繼續往後尋找最近逗號,當遞迴終點大於 0(表示 CHARINDEX() 有找到逗號),遞迴就必須繼續,等於 0 的話,遞迴就會停止

此圖為 CTE 跑完後每篇文章的每個關鍵字起始和結束位置一覽表。

正常情況下,CTE 跑出的起始和結束位置就可以找出關鍵字,但因 CTE 是用 CHARINDEX() 是否找到逗號來當成停止條件,因此每篇文章最後的關鍵字終點必為 0。

利用 NULLIF() 來尋找終點為 0 的資料,把它取代為 NULL ,再利用 ISNULL() 來判斷,不是 NULL 就直接抓取終點,NULL 則是找關鍵字總長度來當成終點,終點經過轉換後,就可以利用 SUBSTRING() 來抓取每個關鍵字。

星期五, 6月 08, 2012

[SQL] 小型索引

維護索引時發現,有些索引不論怎麼 ALTER INDEX REBUILD,avg_fragmentation_in_percent 完全沒有變化或是效果不彰(仍大於 MS 建議的 30 %)。

重新組織和重建索引 中這段文字點出問題所在
一般來說,小型索引的片段經常是無法控制的。小型索引的頁面會儲存在混合範圍上,混合範圍最多可由八個物件所共用,所以當重新組織或重建索引之後,小型索引中的片段可能不會減少。
利用 sys.dm_db_index_physical_stats DMV 判斷重整的兩個指標為
  1. avg_fragmentation_in_percent - 邏輯片段的百分比 (索引中失序的頁面) - 越低越好
  2. avg_fragment_size_in_pages - 在索引中一個片段的頁面平均數目 - 越高越好
而 avg_fragmentation_in_percent 在 5% 和 30% 之間,使用 ALTER INDEX REORGANIZE,而大於 30% 使用 ALTER INDEX REBUILD 來重整索引。

但對於小型索引來講,sys.dm_db_index_physical_stats 的 Page_Count(總索引頁數)也是一個重要指標,Page_Count 太小的索引,即使 avg_fragmentation_in_percent 很高,重整時也不會有作用或效果不彰的情況。
  • 以下是測試結果(索引填充因子皆為預設 0 、表格中的 fragmentation 代表 avg_fragmentation_in_percent ):

重整前
重整後

資料筆數
fragmentation
Page_Count
fragmentation
Page_Count
重整
效果
305311
95.35
13937
0.0137
7270
Good
26033
92.98
699
0.6172
162
Good
11528
48.087
915
0
706
Good
3225
84.426
122
33.333
21
效果差
340
81.818
11
85.714
7
更糟糕
801
83.333
6
80
5
沒效果

* 測試資料庫約為 2G ,只有少數幾個 Table 資料量較龐大。

小型索引這個名詞很模糊,到底怎樣才算小,在這篇文章中 SQL Server: Simple Method to Resolve All Indexes Fragmentation 重整時 Page_Count 小於 8 會忽略,這篇 SQL Server Index Maintenance Performance Tuning for Large Tables 則是預設 128 以下不動作,以測試資料來看, Page_Count 在 500 以上, ALTER INDEX REBUILD 效果較明顯。
  • 20130818 補充
閱讀 Where do the Books Online index fragmentation thresholds come from? ,該大師建議 page_count 小於 1000 時,就不要理會該索引破碎程度。
  • 20211206 補充
在 SQL Server 2019 維護計畫中發現,重建索引的頁面計數 (Page Count) 預設是 1,000

[SQL] 小型索引-1

星期五, 6月 01, 2012

[SQL] 模擬死結產生

根據 MSDN 將死結數量降至最低 裡的圖型模擬死結產生 ~~

[SQL] 模擬死結產生

在 SSMS 內開啟兩個 T-SQL 查詢(兩個執行緒),利用下面語法來執行,請先執行 T-SQL 查詢 1,再執行 T-SQL 查詢 2。

步驟簡易說明:
  • Step 1:建立一個 T-SQL 查詢 1,開啟一個交易,並進行更新 Supplier 資料
  • Step 2:建立另一個 T-SQL 查詢 2,開啟一個交易,並進行更新 Part
  • Step 3:回到 T-SQL 查詢 1,更新 Part
  • Step 4:回到 T-SQL 查詢 2,更新 Supplier
藉此產生一個死結。

  • 建立測試資料
IF OBJECT_ID('Supplier') IS NOT NULL
  DROP TABLE Supplier

IF OBJECT_ID('Part') IS NOT NULL
  DROP TABLE Part

CREATE TABLE Supplier 
  (
    SPLNO char(5),
    SPLName char(10),
    CONSTRAINT [PK_Supplier] PRIMARY KEY CLUSTERED ([SPLNO] ASC)
  )

CREATE TABLE Part
  (
    SPLNO char(5),
    Product char(50),
    CONSTRAINT [PK_Part] PRIMARY KEY CLUSTERED ([SPLNO] ASC,[Product] ASC)
  )

INSERT INTO Supplier VALUES('00000','Microsoft')
INSERT INTO Part VALUES('00000','SQL Server 2012')
  • T-SQL 查詢 1
BEGIN TRANSACTION
UPDATE Supplier SET SPLName = 'Microsoft' WHERE SPLNO = '00000' -- Step 1
WAITFOR DELAY '00:00:05'
UPDATE Part SET Product = 'SQL Server 2012' WHERE Product = 'SQL Server 2012' -- Step 3
COMMIT TRANSACTION
  • T-SQL 查詢 2
BEGIN TRANSACTION
UPDATE Part SET Product = 'SQL Server 2012' WHERE Product = 'SQL Server 2012' -- Step 2
WAITFOR DELAY '00:00:05'
UPDATE Supplier SET SPLName = 'Microsoft' WHERE SPLNO = '00000' -- Step 4
COMMIT TRANSACTION
  • 死結錯誤訊息
訊息 1205,層級 13,狀態 45,行 1
交易 (處理序識別碼 52) 在 鎖定 資源上被另一個處理序鎖死並已被選擇作為死結的犧牲者。請重新執行該交易。