Как эффективно имитировать ограничение внешнего ключа, если поле, на которое оно ссылается, автоинкрементно? - PullRequest
1 голос
/ 16 марта 2012

Я пытаюсь создать приложение базы данных для книжного магазина.

В спецификации: «После регистрации пользователь может заказать одну или несколько книг. Об общей сумме заказа следует сообщить ему / ей. Пользователь может заказать несколько копий книги один или несколько раз».

Общая сумма не кажется такой уж плохой.

Вот две соответствующие таблицы:

Заказ ( идентификатор заказа : INT (11), логин: VARCHAR (45), дата: DATETIME)

BooksOrdered ( orderID : INT (11), ISBN : VARCHAR (45), количество: INT (11))

Предметы, выделенные жирным шрифтом, - это PK.

Теперь вот что: наша база данных не допускает использование FK для проблем с производительностью, поэтому я должен имитировать их на прикладном уровне. BooksOrdered.orderID действительно FK, но не так много. Кроме того, Order.orderID является автоинкрементным.

Я пытаюсь выяснить, как убедиться, что идентификатор заказа совпадает (имитируют ограничение внешнего ключа) при вставке новых заказов.

В принципе, я не понимаю, как эффективно вставить ордер с помощью ArrayList (BookOrder просто будет содержать ISBN и счетчик).

Одно решение, о котором я подумал:

Каждый раз, когда я хочу добавить строку в BooksOrdered, просто извлекаем самый большой orderID из Order. Это кажется неэффективным, и я думаю, что могут быть другие проблемы с ним (одновременный доступ / вставки?).

Поэтому я спрашиваю вас, как мне подражать этому автоинкрементному ФК? Или вы предлагаете мне реструктурировать свои столы?

Или есть способ, которым я могу волшебным образом захватить последний ордер, который я вставил в ордер ... скажем, в процессе вставки?

EDIT:

Хорошо, у меня есть следующая неполная функция:

public int orderBooks(String loginName, ArrayList<BookOrder> bookOrders) throws Exception{

    int id = -1;
    //Working on the date situation
    java.util.Date today = new java.util.Date();
    Timestamp sqlDate = new java.sql.Timestamp(today.getTime());

    Connector con=null;
    String query = "INSERT INTO Order (loginName, date) " +
            " VALUES ('"+loginName+"', "+sqlDate+")";
    ResultSet rs; 


    try{
        con= new Connector();
        con.stmt.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
        rs = con.stmt.getGeneratedKeys();
        if (rs.next()) {
            id = rs.getInt(1);
        } else {
            throw(new Exception()); // mmm...
            // throw an exception from here
        }
        con.stmt.close();
    } catch(Exception e) {
        System.err.println("Unable to execute query:"+query+"\n");
        System.err.println(e.getMessage());
        throw(e);
    }
    finally
     {
         if (con != null)
         {
             try
             {
                 con.closeConnection();
             }
             catch (Exception e) { /* ignore close errors */ }
         }
     }




    return id;
}

Теперь, куда мне поместить id = stmt.executeUpdate (query, Statement.RETURN_GENERATED_KEYS) ;? Я поставил это в правильном месте? (продолжает работать над созданием тестируемого прототипа)

1 Ответ

0 голосов
/ 16 марта 2012

Какой язык вы используете? Скорее всего, он будет иметь функцию для извлечения последнего автоинкрементного значения из вашего текущего дескриптора базы данных. Например, в PHP вы должны использовать mysql_insert_id() ( doc ). В Perl DBI вы можете использовать last_insert_id(). ( DBI Doc )

Если вы хотите установить флаг в executeUpdate:

id = stmt.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);

Также есть функция stmt.getGeneratedKeys(). См. Документы . Запись executeUpdate находится прямо под getGeneratedKeys.

...