星期二, 6月 25, 2019

[VFP] CursorAdapter 使用 Store Procedure - 回傳 identity

該篇為 [VFP] CursorAdapter 使用 Store Procedure 的延續利用 identity 當成 PK,insert 時都有取回 identity 值的需求,筆記一下
CREATE PROCEDURE [dbo].[dmlEmployee_Insert]
(
  @UserName char(10) ,
  @HireDate datetime ,
  @Age int ,
  @UserID int output
)
AS
BEGIN

  SET NOCOUNT ON;

  INSERT INTO Employee (UserName , HireDate , Age)
   VALUES(@UserName , @HireDate , @Age)

  SET @UserID = SCOPE_IDENTITY()
END
GO
Insert Command 內宣告參數 (@lcUserID、名稱可以自訂) 來接就行

在 VFP 中顯示 identity 值
lcUserID = ""
lbResult = TABLEUPDATE(1,.T.,"Employee")
IF lbResult = .F.
  AERROR(laError)
  MESSAGEBOX(laError(2))
ELSE 
  MESSAGEBOX(lcUserID)
ENDIF 

星期一, 6月 24, 2019

[VFP] CursorAdapter 使用 Store Procedure

跟同事討論時突然想到,VFP 都是透過 SPT 來呼叫 SP,所以直覺是 CursorAdapter 無法做到,能呼叫 SP 的話,可以把商業邏輯封在 SP 內,可以解決不少麻煩,查資料發現是可以的,弄個小範例來記錄重點

SQL Server 內相關設定

在 TempDB 內建立 Employee Table
USE [tempdb]
GO

CREATE TABLE [dbo].[Employee](
  [UserID] [int] IDENTITY(1,1) NOT NULL Primary Key,
  [UserName] [char](20) NULL,
  [HireDate] [datetime] NULL,
  [Age] [tinyint] NULL)
GO

INSERT INTO Employee (UserName , HireDate , Age)
  VALUES('張三' , '2019-06-01' , 30)
INSERT INTO Employee (UserName , HireDate , Age)
  VALUES('李四' , '2018-12-11' , 25) 

建立 Insert、Update 和 Delete Store Procedure
-- Insert
CREATE PROCEDURE [dbo].[dmlEmployee_Insert]
(
  @UserName char(10) ,
  @HireDate datetime ,
  @Age int ,
  @UserID int output
)
AS
BEGIN

  SET NOCOUNT ON;

  INSERT INTO Employee (UserName , HireDate , Age)
   VALUES(@UserName , @HireDate , @Age)

  SET @UserID = SCOPE_IDENTITY()
END
GO

-- Update
CREATE PROCEDURE [dbo].[dmlEmployee_Update]
(
  @UserID int ,
  @UserName char(10) ,
  @HireDate datetime ,
  @Age int
)
AS
BEGIN

  SET NOCOUNT ON;

  UPDATE Employee
  SET UserName = @UserName , 
   HireDate = @HireDate , 
   Age = @Age
  WHERE UserID = @UserID
END
GO

-- Delete
CREATE PROCEDURE [dbo].[dmlEmployee_Delete]
(
  @UserID int
)
AS
BEGIN

  SET NOCOUNT ON;

  DELETE FROM Employee WHERE UserID = @UserID
END
GO
CursorAdapter 設定

AutoUpdate Tag => Advanced Button

覆蓋自動產生的 insert、update 和 delete 語法




利用 SQL Profile 來側錄 insert、update 和 delete 語法,確定有使用 SP 



星期三, 6月 19, 2019

[SQL] 建立 Foreign Key

同事詢問為什麼 FK 建不起來,了解情況後發現,因為程式需求,要把原 master-detail 架構下的 master PK 換成其他欄位,但希望還是可以維持原有的 FK 存在,一開始直覺是 FK 就建不起來,後來查資料發現,原來除了 PK 外,有 Unique 也可以

doc 上重點摘要
外部索引鍵條件約束不一定只能連結到另一個資料表中的主索引鍵條件約束;它也可以定義成參考另一個資料表中 UNIQUE 條件約束的資料行。
透過 SSMS 來建立 FK,其實訊息也說得很清楚,需要 PK 或 Unique

[SQL] 建立 Foreign Key

簡易練習一下
USE tempdb
GO

-- 建立 tbMaster、tbDetail Table
CREATE TABLE tbMaster (MID int unique) -- 設定 MID 欄位為 Unique
CREATE TABLE tbDetail (DID int Primary key not null, MID int)
GO

-- 設定 FK
ALTER TABLE [tbDetail]  WITH CHECK ADD CONSTRAINT [FK_tbDetail_tbMaster] FOREIGN KEY(MID)
REFERENCES [tbMaster] (MID)
GO

[SQL] 建立 Foreign Key-3

[SQL] 建立 Foreign Key-2

星期二, 6月 18, 2019

[SSMS] SQLFile 預設編碼

對 TSQL Script 進行版控並 push 到 Azure DevOps 上時,才發現 Script 檔案編碼是 big5
手動變更 Script 檔案編碼,先另存該檔案
選擇 [以編碼方式儲存] 該檔案

預設為 [繁體中文 (Big5) - 子碼頁 950],修改為 [Unicode (UTF-8 有簽章) - 子碼頁 65001]
SSMS TSQL Script 檔案,是以 SQLFile 為範本產生,因此只要修正 SQL File 編碼,以後就通通都是 UTF-8

目前使用的 SSMS 是 V18 版本,可以在 C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE\SqlWorkbenchProjectItems\Sql 找到 SQLFile,只要根據上述步驟,把該檔案編碼改為 UTF-8,以後新增 TSQL Script 檔案就會是 UTF-8

星期五, 6月 07, 2019

[SQL] 大量匯入與 Identity

利用 Bulk Insert 時遇上 Identity 欄位問題,發現 MSDN 文章 - 大量匯入資料時保留識別值,明確指出 Bulk Insert 必須指定 KEEPIDENTITY 才能保留,否則會在自動產生喔

MSDN 說明
您可以將包含識別值的資料檔案大量匯入 Microsoft SQL Server 的執行個體中。 根據預設,會忽略所匯入資料檔案中的識別欄位值, SQL Server 會自動指定唯一值。 唯一值的依據是資料表建立期間所指定的初始值及累加值。

[SQL] 大量匯入與 Identity


測試 KeepIdentity 效果

建立測試資料 Identity 為 1、3、5 三筆奇數資料,並分別利用 Bulk Insert 匯入資料
  • 左圖:指定 KeepIdentity,identity 仍為 1、3、5
  • 右圖:預設為沒有指定 KeepIdentity,identity 會自動產生
[SQL] 大量匯入與 Identity-2