第五十六章 SQL命令 INSERT OR UPDATE

第五十六章 SQL命令 INSERT OR UPDATE

在表中添加新行或更新表中的現(xiàn)有行。

大綱

INSERT OR UPDATE [%keyword] [INTO] table
          SET column = scalar-expression {,column2 = scalar-expression2} ...  |
          [ (column{,column2} ...) ] VALUES (scalar-expression {,scalar-expression2} ...)  |
          VALUES :array()  |
          [  (column{,column2} ...) ] query  |
          DEFAULT VALUES

參數(shù)

  • %keyword - 可選-以下一個(gè)或多個(gè)關(guān)鍵字選項(xiàng),以空格分隔:%NOCHECK%NOFPLAN、%NOINDEX、%NOJOURN、%NOLOCK、%NOTRIGGER%PROFILE、%PROFILE_ALL
  • table - 要對(duì)其執(zhí)行插入操作的表或視圖的名稱。此參數(shù)可以是子查詢。INTO關(guān)鍵字是可選的。
  • column - 可選-與提供的值列表順序?qū)?yīng)的列名或以逗號(hào)分隔的列名列表。如果省略,值列表將按列號(hào)順序應(yīng)用于所有列。
  • scalar-expression - 為相應(yīng)列字段提供數(shù)據(jù)值的標(biāo)量表達(dá)式或以逗號(hào)分隔的標(biāo)量表達(dá)式列表。
  • :array() - 僅嵌入式SQL-指定為主機(jī)變量的值的動(dòng)態(tài)本地?cái)?shù)組。必須未指定數(shù)組的最低下標(biāo)級(jí)別。因此:myupdates(), :myupdates(5,):myupdates(1,1,)都是有效的規(guī)范。
  • query - 一種選擇查詢,其結(jié)果集為一行或多行的相應(yīng)列字段提供數(shù)據(jù)值。

描述

INSERTUPDATE語(yǔ)句是INSERT語(yǔ)句的擴(kuò)展(它與INSERT語(yǔ)句非常相似):

  • 如果指定的記錄不存在,則INSERTUPDATE執(zhí)行INSERT。
  • 如果指定的記錄已存在,則INSERTUPDATE執(zhí)行更新。它使用指定的字段值更新記錄。即使指定的數(shù)據(jù)與現(xiàn)有數(shù)據(jù)相同,也會(huì)進(jìn)行更新。

INSERTUPDATE通過(guò)將唯一關(guān)鍵字字段值與現(xiàn)有數(shù)據(jù)值匹配來(lái)確定記錄是否存在。如果發(fā)生違反唯一鍵約束的情況,則INSERTUPDATE將執(zhí)行UPDATE操作。請(qǐng)注意,唯一鍵字段值可能不是在INSERTUPDATE中顯式指定的值;它可能是列默認(rèn)值或計(jì)算值的結(jié)果。當(dāng)對(duì)切片表運(yùn)行INSERTUPDATE時(shí),如果切片鍵與UNIQUE KEY約束相同(或是其子集),則INSERTUPDATE將執(zhí)行UPDATE操作。如果INSERTUPDATE因?yàn)檎业饺魏纹渌ㄒ绘I值(不是切片鍵)而嘗試執(zhí)行更新,則該命令會(huì)失敗,并由于UNIQUE約束失敗而出現(xiàn)SQLCODE-119錯(cuò)誤。

注意:由于%NOCHECK關(guān)鍵字禁用唯一值檢查,因此INSERTUPDATE %NOCHECK總是導(dǎo)致INSERT操作。因此,請(qǐng)不要指定%NOCHECK。

單個(gè)記錄的INSERTUPDATE始終將%ROWCOUNT變量設(shè)置為1,并將已插入或更新的行的%ROWID變量設(shè)置為1。

INSERTUPDATE語(yǔ)句與SELECT語(yǔ)句組合可以插入和/或更新多個(gè)表行。

INSERTUPDATE使用相同的語(yǔ)法,并且通常具有與INSERT語(yǔ)句相同的功能和限制。這里描述了插入或更新的特殊注意事項(xiàng)。除非此處另有說(shuō)明,否則請(qǐng)參閱插入以了解詳細(xì)信息。

權(quán)限

INSERTUPDATE同時(shí)需要插入和更新權(quán)限。必須將這些權(quán)限作為表級(jí)權(quán)限或列級(jí)權(quán)限擁有。對(duì)于表級(jí)權(quán)限:

  • 無(wú)論實(shí)際執(zhí)行的是什么操作,用戶都必須擁有對(duì)指定表的INSERTUPDATE權(quán)限。
  • 如果使用SELECT查詢插入或更新另一個(gè)表中的數(shù)據(jù),則用戶必須對(duì)該表具有SELECT權(quán)限。

如果用戶是表的所有者(創(chuàng)建者),則會(huì)自動(dòng)授予該用戶對(duì)該表的所有權(quán)限。否則,必須授予用戶對(duì)該表的權(quán)限。否則將導(dǎo)致SQLCODE-99錯(cuò)誤,因?yàn)?code>%msg用戶‘name’沒(méi)有該操作的特權(quán)??梢酝ㄟ^(guò)調(diào)用%CHECKPRIV命令來(lái)確定當(dāng)前用戶是否具有適當(dāng)?shù)臋?quán)限??梢允褂?code>GRANT命令為用戶分配表權(quán)限。

IDKEY字段

可以插入IDKEY字段值,但不能更新IDKEY字段值。如果表具有IDKEY索引和另一個(gè)唯一鍵約束,則INSERTUPDATE將匹配這些字段以確定是執(zhí)行INSERT還是UPDATE。如果另一個(gè)鍵約束失敗,則強(qiáng)制INSERTUPDATE執(zhí)行更新而不是INSERT。但是,如果指定的IDKEY字段值與現(xiàn)有IDKEY字段值不匹配,則此更新將失敗并生成SQLCODE-107錯(cuò)誤,因?yàn)楦抡趪L試修改IDKEY字段。

例如,表MyTest定義了四個(gè)字段:A、B、C、D,具有IDKEY(A,B)Unique(C,D)約束。該表包含以下記錄:

Row 1: A=1, B=1, C=2, D=2

Row 2: A=1, B=2, C=3, D=4

調(diào)用INSERTUPDATE ABC(A,B,C,D)(2,2,3,4),因?yàn)?code>UNIQUE(C,D)約束失敗,所以該語(yǔ)句不能執(zhí)行INSERT。相反,它會(huì)嘗試更新第2行。第2行的IDKEY為(1,2),因此INSERTUPDATE語(yǔ)句將嘗試將字段A的值從1更改為2。但無(wú)法更改IDKEY值,因此更新失敗,并顯示SQLCODE-107錯(cuò)誤。

計(jì)數(shù)器字段

當(dāng)執(zhí)行INSERTUPDATE時(shí), IRIS最初假定操作將是INSERT。因此,它將用于向串行(%Library.Counter)字段提供整數(shù)的內(nèi)部計(jì)數(shù)器加1。INSERT使用這些遞增的計(jì)數(shù)器值將整數(shù)值分配給這些字段。但是,如果 IRIS確定該操作需要更新,則INSERTUPDATE已經(jīng)遞增了內(nèi)部計(jì)數(shù)器,但它不會(huì)將這些遞增的整數(shù)值分配給計(jì)數(shù)器字段。如果下一個(gè)操作是INSERT,則會(huì)導(dǎo)致這些字段的整數(shù)序列出現(xiàn)間隙。下面的示例顯示了這一點(diǎn):

  1. 內(nèi)部計(jì)數(shù)器值為4。INSERTUPDATE遞增內(nèi)部計(jì)數(shù)器,然后插入行5:內(nèi)部計(jì)數(shù)器=5,串行字段值=5
  2. INSERTUPDATE遞增內(nèi)部計(jì)數(shù)器,然后確定它必須對(duì)現(xiàn)有行執(zhí)行更新:INTERNAL COUNTER=6,不更改字段計(jì)數(shù)器。
  3. INSERTUPDATE遞增內(nèi)部計(jì)數(shù)器,然后插入一行:內(nèi)部計(jì)數(shù)器=7,序列字段值=7

Identity和RowID字段

INSERTUPDATE對(duì)RowId值分配的影響取決于是否存在標(biāo)識(shí)字段:

  • 如果沒(méi)有為表定義標(biāo)識(shí)字段,則INSERT操作會(huì)導(dǎo)致 IRIS自動(dòng)將下一個(gè)連續(xù)整數(shù)值分配給ID(RowID)字段。更新操作對(duì)后續(xù)插入沒(méi)有影響。因此,INSERTUPDATE執(zhí)行與INSERT相同的INSERT操作。
  • 如果為表定義了標(biāo)識(shí)字段,則INSERTUPDATE會(huì)導(dǎo)致 IRIS在確定操作是INSERT還是UPDATE之前,將用于向標(biāo)識(shí)字段提供整數(shù)的內(nèi)部計(jì)數(shù)器加1。插入操作將該遞增的計(jì)數(shù)器值分配給標(biāo)識(shí)字段。但是,如果 IRIS確定INSERTUPDATE操作需要更新,則它已經(jīng)遞增了內(nèi)部計(jì)數(shù)器,但不會(huì)分配這些遞增的整數(shù)值。如果下一個(gè)INSERTUPDATE操作是INSERT,則會(huì)導(dǎo)致標(biāo)識(shí)字段的整數(shù)序列出現(xiàn)間隙。RowID字段值取自Identity字段值,導(dǎo)致ID(RowID)整數(shù)值的分配存在差距。

示例

以下五個(gè)示例:創(chuàng)建一個(gè)新表(SQLUser.CaveDwell);使用INSERTUPDATE用數(shù)據(jù)填充該表;使用INSERTUPDATE添加新行并更新現(xiàn)有行;使用SELECT*顯示數(shù)據(jù);以及刪除該表。

以下示例使用CREATE TABLE創(chuàng)建具有唯一字段(NUM)的表:

ClassMethod InsertOrUpdate()
{
    &sql(
        CREATE TABLE SQLUser.CaveDwellers (
            Num          INT UNIQUE,
            CaveCluster  CHAR(80) NOT NULL,
            Troglodyte   CHAR(50) NOT NULL,
            CONSTRAINT CaveDwellerPK PRIMARY KEY (Num)
        )
    )
    if SQLCODE = 0 { 
        w !,"表創(chuàng)建" 
    } elseif SQLCODE = -201 { 
        w !,"表已經(jīng)存在" 
    } else { 
        w !,"SQL表創(chuàng)建錯(cuò)誤代碼: ",SQLCODE
        q 
    }
}

下面的示例使用類定義定義同一個(gè)表,為num定義唯一鍵:

Class User.CaveDwellers Extends %Persistent [ ClassType = persistent, DdlAllowed, Final, Owner = {yx}, ProcedureBlock, SqlRowIdPrivate, SqlTableName = CaveDwellers ]
{

Property Num As %Library.Integer(MAXVAL = 2147483647, MINVAL = -2147483648) [ SqlColumnNumber = 2 ];

Property CaveCluster As %Library.String(MAXLEN = 80) [ Required, SqlColumnNumber = 3 ];

Property Troglodyte As %Library.String(MAXLEN = 50) [ Required, SqlColumnNumber = 4 ];

/// DDL Unique Key Specification
Index CAVEDWELLERSUNIQUE1 On Num [ SqlName = CAVEDWELLERS_UNIQUE1, Unique ];

/// DDL Primary Key Specification
Index CaveDwellerPK On Num [ PrimaryKey, Type = index, Unique ];

/// Bitmap Extent Index auto-generated by DDL CREATE TABLE statement.  Do not edit the SqlName of this index.
Index DDLBEIndex [ Extent, SqlName = "%%DDLBEIndex", Type = bitmap ];

}

SELECT * FROM SQLUser.CaveDwellers ORDER BY Num

以任何順序運(yùn)行以下兩個(gè)示例一次或多次。他們將插入記錄15。如果記錄4已經(jīng)存在,插入或更新將更新它。使用SELECT *示例顯示表格數(shù)據(jù):

ClassMethod InsertOrUpdate1()
{

    &sql(
        INSERT OR UPDATE INTO SQLUser.CaveDwellers 
        (
            Num, CaveCluster, Troglodyte
        ) 
        VALUES 
        (
            3, 'Bedrock', 'Flintstone,Fred'
        )
    )
    if SQLCODE = 0 { 
        SET rcount=%ROWCOUNT 
    }
    &sql(
        INSERT OR UPDATE INTO SQLUser.CaveDwellers 
        (
            Num, CaveCluster, Troglodyte
        ) 
        VALUES 
        (
            4, 'Bedrock1', 'Flintstone,Wilma'
        )
    )
    if SQLCODE = 0 { 
        s rcount = rcount + %ROWCOUNT 
        w !,rcount," records inserted/updated" 
    } else { 
        w !,"Insert/Update failed, SQLCODE=",SQLCODE 
    }
}
ClassMethod InsertOrUpdate2()
{

    n SQLCODE,%ROWCOUNT,%ROWID
    &sql(
        INSERT OR UPDATE SQLUser.CaveDwellers
        (
            Num,CaveCluster,Troglodyte
        )
        SELECT %ID,Home_City,Name
        FROM Sample.Person
        WHERE %ID BETWEEN 2 AND 5)
    if SQLCODE=0 {
        w !,"Insert/Update succeeded"
        w !,%ROWCOUNT," records inserted/updated"
        w !,"Row ID=",%ROWID 
    } else {
        w !,"Insert/Update failed, SQLCODE=",SQLCODE 
    }
}

以下示例刪除該表:

ClassMethod InsertOrUpdate3()
{
    &sql(DROP TABLE SQLUser.CaveDwellers)
    if SQLCODE = 0 {
        w !,"表已刪除" 
    } elseif SQLCODE = -30 {
        w !,"表不存在"
    } else {
        w !,"刪除表失敗. SQLCODE=",SQLCODE 
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容