2009-08-26 2 views
12

Я знаю, что в Oracle Я могу получить сгенерированный идентификатор (или любой другой столбец) из вставленной строки в качестве выходного параметра. Ex:Как получить сгенерированный идентификатор из вставленной строки с помощью ExecuteScalar?

insert into foo values('foo','bar') returning id into :myOutputParameter 

Есть ли способ сделать то же самое, но с использованием ExecuteScalar вместо ExecuteNonQuery?

Я не хочу использовать выходные параметры или хранимые процедуры.

ps: Я использую Oracle, а не сервер sql !!!

+0

Подставляя это как комментарий, как это спекулятивный, но Sql Server га «@@ SCOPE_IDENTITY», так что оператор может быть «вставить фо ...., выберите @@ SCOPE_IDENTITY» ... Есть ли у Oracle что-то аналогичный? – Rob

+2

Это будет ответ :) – andrecarlucci

+0

Как и для SQL Server, я не знаю об этой системной переменной @@ SCOPE_IDENTITY, поэтому я знаю о скалярной функции IDENT_CURRENT, которая делает то же самое (SELECT IDENT_CURRENT (N'TableName)) –

ответ

6

Oracle использует последовательности как для своих столбцов идентичности, если можно так выразиться.

Если вы установили последовательность для первичного ключа вашей таблицы, вам также необходимо написать триггер, который будет вставлять Sequence.NextValue или около того в поле первичного ключа.

Предполагая, что вы уже знакомы с этой концепцией, просто запросите свою последовательность, тогда вы получите ответ. То, что очень хорошо практикуется в Oracle, - это сделать себе функцию, которая вернет INT, а затем внутри вашей функции вы выполните свой INSERT. Предполагая, что вы правильно настроили свой триггер, вы сможете вернуть значение своей последовательности, запросив его.

Вот пример:

CREATE TABLE my_table (
    id_my_table INT PRIMARY KEY 
    description VARCHAR2(100) NOT NULL 
) 

CREATE SEQUENCE my_table_seq 
    MINVALUE 1 
    MAXVALUE 1000 
    START WITH 1 
    INCREMENT BY 2 
    CACHE 5; 

Если вы хотите управлять автоинкрементируемыми себя, вот как:

INSERT INTO my_table (
    id_my_table, 
    description 
) VALUES (my_table_seq.NEXTVAL, "Some description"); 
COMMIT; 

С другой стороны, если вы хотите, чтобы не заботиться о ПЕРВИЧНОМ KEY, вы можете продолжить с помощью триггера.

CREATE OR REPLACE TRIGGER my_table_insert_trg 
    BEFORE INSERT ON my_table FOR EACH ROW 
BEGIN 
    SELECT my_table_seq.NEXTVAL INTO :NEW.id_my_table FROM DUAL; 
END; 

Затем, когда вы вставки, просто введите оператор INSERT следующим образом:

INSERT INTO my_table (description) VALUES ("Some other description"); 
COMMIT; 

После INSERT, я предполагаю, что вы хотите

SELECT my_table_seq.CURRVAL 

или что-то вроде этого, чтобы выбрать фактическое значение вашей последовательности.

Вот некоторые ссылки, которые помогут:

http://www.orafaq.com/wiki/Sequence

http://www.orafaq.com/wiki/AutoNumber_and_Identity_columns

Надеется, что это помогает!

+0

Привет, Ничего, я не думал о seq.CURRVAL. Но разве это спасение? Я имею в виду, если кто-то вставляет строку между двумя моими вызовами (insert, select)? – andrecarlucci

+0

Обычно такие операции относятся к вашему соединению/сеансу базы данных, чтобы предотвратить такое возникновение. Я не могу найти его в black & white для Oracle, но так он работает для MySQL, Access, SQL Server и т. Д. –

+1

Oracle будет выполнять вставки последовательно. Как только он прошел через первый оператор INSERT и вернул значение новой текущей последовательности, он выполнит другую вставку. Как заявил г-н Сумасшедший Джо Маллой, это не имеет значения, как это сделать. :) Мы не должны забывать, что Oracle работает транзакционным способом. Таким образом, NEXTVALUE не будет выбрано из последовательности, если оператор INSERT не COMMITED. В любом случае, если я правильно помню, во время выполнения транзакции есть где-то где-то (TABLE или SEQUENCE). –

24

Если вы находитесь на oracle, вам нужно использовать ExecuteNonQuery и ResultParameter. Невозможно написать это как запрос.

using (OracleCommand cmd = con.CreateCommand()) { 
    cmd.CommandText = "insert into foo values('foo','bar') returning id into :myOutputParameter"; 
    cmd.Parameters.Add(new OracleParameter("myOutputParameter", OracleDbType.Decimal), ParameterDirection.ReturnValue); 
    cmd.ExecuteNonQuery(); // an INSERT is always a Non Query 
    return Convert.ToDecimal(cmd.Parameters["myOutputParameter"].Value); 
} 
+0

Что является разницей между параметрами ParameterDirection.ReturnValue и ParameterDirection.Output? – Timeless

+0

ParameterDirection.ReturnValue является результатом функции ParameterDirection.Output для параметров в методах (функциях или процедурах), которые определены как out или inout. – Christian13467

+1

Sigh Я продолжаю получать «ORA-12537: Network Session: End of file» в ExecuteNonQuery независимо от того, что я пытаюсь :( –

1

один из возможных способов, если вы можете добавить один столбец с именем «guid» в таблицу: при вставке одной записи из C#, сгенерируйте направляющую и запишите ее в столбец guid. затем выполнить отборное с генерируемым GUID, и у вас есть идентификатор вставленной записи :)

0
Select t.userid_pk From Crm_User_Info T 
Where T.Rowid = (select max(t.rowid) from crm_user_info t) 

это вернет ваш необходимый идентификатор

2

Вы можете использовать ниже код.

using (OracleCommand cmd = conn.CreateCommand()) 
    { 
     cmd.CommandText = @"INSERT INTO my_table(name, address) 
      VALUES ('Girish','Gurgaon India') 
      RETURNING my_id INTO :my_id_param"; 
     OracleParameter outputParameter = new OracleParameter("my_id_param", OracleDbType.Decimal); 
     outputParameter.Direction = ParameterDirection.Output; 
     cmd.Parameters.Add(outputParameter);   
     cmd.ExecuteNonQuery();   
     return Convert.ToDecimal(outputParameter.Value); 
    } 
Смежные вопросы