【问题标题】:Insert/Update records in Oracle SQL database?在 Oracle SQL 数据库中插入/更新记录?
【发布时间】:2019-04-19 17:21:11
【问题描述】:

我最近开始使用 Oracle。在此之前,我使用 SQL Server 2008/2012。我注意到 Oracle 和 SQL Server 之间存在一些差异。我在 SQL Server 中创建了包含一些基本列的表,例如名字、姓氏、电子邮件等。这是我的表结构的示例:

Name          Data Type  Size   Not Null
RECORDID      NUMBER            true    //This is primary key (auto increment)  
FIRST         VARCHAR2   50     true        
LAST          VARCHAR2   50     true        
EMAIL         VARCHAR2   320    true        
PHONE         CHAR       10     true        
FILEPATH      VARCHAR2   1000   false       
TYPE          CHAR       1      true        
SUBJECT       VARCHAR2   100    true        
DESCRIPTION   VARCHAR    4000   true    // This should be varchar(max)  
ACTIONDATE    DATE              true    

我在 Oracle SQL Developer 中使用Identity Column 选项将RecordID 设置为列序列。这与 SQL Server 不同,我正在寻找相同的行为。该列应为添加到表中的每个新行自动递增。

这是在 Oracle 中设置身份列的正确方法吗?这是我的插入语句的示例:

<cfquery name="insertRec" datasource="test">
    INSERT INTO Table1 (
        RecordID, First, Last, Email, Phone, 
        FilePath, Type, Subject, Description, ActionDate 
    )VALUES(
        RecID_SEQ1.NEXTVAL,
        <cfqueryparam cfsqltype="cf_sql_varchar" value="trim(#form.first#)" maxlength="50">,
        <cfqueryparam cfsqltype="cf_sql_varchar" value="trim(#form.last#)" maxlength="50">,
        <cfqueryparam cfsqltype="cf_sql_varchar" value="trim(#form.email#)" maxlength="50">,
        <cfqueryparam cfsqltype="cf_sql_char" value="trim(#form.phone#)" maxlength="10">,
        <cfqueryparam cfsqltype="cf_sql_varchar" value="trim(#form.file#)" maxlength="1000">,
        <cfqueryparam cfsqltype="cf_sql_char" value="trim(#form.type#)" maxlength="1">,
        <cfqueryparam cfsqltype="cf_sql_varchar" value="trim(#form.subject#)" maxlength="100">,
        <cfqueryparam cfsqltype="cf_sql_varchar" value="trim(#form.appdescr#)" maxlength="4000">,
        CURRENT_TIMESTAMP
    )
</cfquery>

在上面的事务中如何设置自增ID?此外,我想返回与 SQL Server 中相同的范围标识。有没有办法在 Oracle 中实现这一目标?如果有人对如何实现这一点或如何改进我上面的代码有任何建议,请告诉我。我刚开始使用 Oracle,这对我来说是新的。

CREATE TABLE "MYDB"."MYTABLE" 
   (    "RECORDID" NUMBER, 
    "FIRST" VARCHAR2(20 BYTE), 
    "LAST" VARCHAR2(20 BYTE), 
    "EMAIL" VARCHAR2(20 BYTE), 
    "PHONE" CHAR(10 BYTE), 
    "FILEPATH" VARCHAR2(20 BYTE), 
    "TYPE" CHAR(1 BYTE), 
    "SUBJECT" VARCHAR2(20 BYTE), 
    "DESCRIPTION" VARCHAR2(20 BYTE), 
    "ACTIONDATE" DATE, 
    "PRIORITY" CHAR(1 BYTE)
   ) SEGMENT CREATION DEFERRED 
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  TABLESPACE "MYDB" ;
--------------------------------------------------------
--  DDL for Index MYTABLE_PK
--------------------------------------------------------

  CREATE UNIQUE INDEX "MYDB"."MYTABLE_PK" ON "MYDB"."MYTABLE" ("RECORDID") 
  PCTFREE 10 INITRANS 2 MAXTRANS 255 NOCOMPRESS LOGGING
  TABLESPACE "MYDB" ;
--------------------------------------------------------
--  DDL for Trigger MYTABLE_TRG
--------------------------------------------------------

  CREATE OR REPLACE TRIGGER "MYDB"."MYTABLE_TRG" 
BEFORE INSERT ON MYTABLE
FOR EACH ROW 
BEGIN
  <<COLUMN_SEQUENCES>>
  BEGIN
    NULL;
  END COLUMN_SEQUENCES;
END;
/
ALTER TRIGGER "MYDB"."MYTABLE_TRG" ENABLE;
--------------------------------------------------------
--  DDL for Trigger MYTABLE_TRG1
--------------------------------------------------------

  CREATE OR REPLACE TRIGGER "MYDB"."MYTABLE_TRG1" 
BEFORE INSERT ON MYTABLE
FOR EACH ROW 
BEGIN
  <<COLUMN_SEQUENCES>>
  BEGIN
    IF INSERTING AND :NEW.RECORDID IS NULL THEN
      SELECT ADPR_SEQ1.NEXTVAL INTO :NEW.RECORDID FROM SYS.DUAL;
    END IF;
  END COLUMN_SEQUENCES;
END;
/

ALTER TRIGGER "MYDB"."MYTABLE_TRG1" ENABLE;

【问题讨论】:

  • “我在 Oracle SQL Developer 中使用 Identity Column 选项将 RecordID 设置为 Column Sequence” - 你在数据建模器中吗?我不知道你是否真的有一个 IDENTITY 列或一个带有序列的触发器。请分享您的表格的完整 DDL。
  • @thatjeffsmith 我使用 Oracle SQL Developer 并在那里设置列标识。不确定这是否会回答您的问题。谢谢。
  • 如果您使用了标识列,则您的 INSERT 中不需要“RecID_SEQ1.NEXTVAL”...数据库为您提供了该值 - 但我们需要查看您的表 DDL。在sql developer中打开表,进入SQL页面,获取代码,添加到你的问题中,我会给你一个好的答案
  • @thatjeffsmith 我添加了 DDL 请看一下,如果有帮助,请告诉我。
  • 好的,您没有标识列...并且您的触发器说如果为 null,则替换为序列中的 nextval,因此您的代码应该只插入所有内容但记录

标签: oracle oracle-sqldeveloper


【解决方案1】:

这正是您想要的 - 它在数据库版本 12c 及更高版本中可用。

生成如下所示的代码 -

CREATE TABLE TABLE4 
(
  COLUMN1 NUMBER GENERATED ALWAYS AS IDENTITY INCREMENT BY 1 START WITH 1 MINVALUE 1 NOT NULL 
, COLUMN2 VARCHAR2(20) 
, CONSTRAINT TABLE4_PK PRIMARY KEY 
  (
    COLUMN1 
  )
  ENABLE 
);

然后进行插入,并取回生成的 ID -

declare
 my_new_record integer;
begin
 insert into table4(column2) values ('Hi') returning column1 into my_new_record;
 dbms_output.put_line('your new record ID is: ' || my_new_record);
end;
/

如果您不在 12c 上,您仍然可以执行所有这些操作 - 您只需创建和维护一个 TRIGGER 和 SEQUENCE 即可。

【讨论】:

  • 我的 Oracle 是 11g,我没有作为身份生成的选项。与 SQL 相比,这似乎有点复杂。 ORACLE 中是否有更好的方法/解决方案来为每条记录创建唯一 ID?谢谢。
  • 已经说过了,触发器和序列组合。 11g 是旧的。比如,5岁多。一旦你达到 12,这一切都变得就像你在“SQL”中所说的那样简单,甚至更容易。
  • 您的问题的根源是如何获取为您的新记录生成的 ID 字段,我们的两个答案都向您展示了这是如何工作的。将其中一项标记为正确。如果您想知道如何在 oracle 中执行触发器/序列 - 更改您的问题,或者更好地查看 stackoverflow.com/questions/11296361/…
  • 好吧,我尝试使用冷融合方法,但他们没有返回 rowid。我在 CF 10 上,也许这就是问题所在。
  • 您无法返回 ROWID - 但您为什么想要或关心 ROWID?还是您的意思是 RECORD_ID?
【解决方案2】:

为了扩展 jeffsmith 所说的内容,您没有有身份列。实际上,您甚至没有主键约束,只有唯一列。标识列如下所示:

create table mytable (
    recordid number generated always by default on null as identity ...

然后,您无需在创建新行时在 INSERT 语句中指定该列。

如果您打算使用这种带有触发的序列模式来插入您的列,您可以通过执行以下操作来获得新的 id:

insert into mytable ( first, ... ) 
values ( 'john', ... )
returning recordid into :myrecordid

这将使用新行的记录 ID 填充 myrecordid

【讨论】:

  • 我正在尝试设置自动增量 ID,它将成为该表的主键。在 SQL 中,我可以通过简单地将自动增量设置为 Yes 并右键单击该列并检查 PK 来做到这一点。可以在Oracle中设置吗?这是推荐的还是有更好的方法?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多