db_affected_rows trong Drupal 7 cho db_query


8

Tôi chỉ nhận thấy rằng @Berdir thật tuyệt khi xóa db_affected_rowskhỏi Drupal 7 . Bây giờ tôi đang tự hỏi thực tiễn tốt nhất bây giờ là gì để phát hiện nếu truy vấn bạn chạy đã thay đổi bất cứ điều gì trong cơ sở dữ liệu.

Một usecase điển hình sẽ là.

db_query(...);
if (!db_affected_rows()) {
  db_query(...);
}

Tôi đã xem xét đối tượng truy vấn được trả về từ db_query, nhưng có vẻ như nó không giúp ích nhiều.

Cập nhật:
Tôi thấy tôi đã không rõ ràng về những trường hợp tôi cần thông tin.

Trường hợp sử dụng hiện tại của tôi, là một khá đơn giản. Tôi có một bảng cho một loại nút với một cột nid và một số cột dữ liệu. Tôi có một biểu mẫu khi gửi biểu mẫu, tôi muốn chèn hoặc cập nhật hàng trong db.

Vấn đề với db_update/ db_insertlà, nếu tôi sử dụng cập nhật trước và chèn nếu cập nhật trả về 0, tôi sẽ không nắm bắt được điều kiện, trong đó biểu mẫu được gửi với giá trị trong db. Nếu tôi sử dụng db_insert trước, điều đó sẽ gây ra lỗi nếu có một hàng trong db.

Tôi cho rằng tôi trong điều kiện cụ thể này có thể chèn một giá trị trống khi nút được tạo và sau đó chỉ sử dụng cập nhật, nhưng đối với một số trường hợp có thể không thực hiện được, nếu tôi cần lưu trữ thông tin được khóa vào cơ sở dữ liệu bên ngoài. Tôi cũng muốn tránh phải phụ thuộc vào các giá trị cơ sở dữ liệu để mã của tôi hoạt động.

Chiến lược thông thường của tôi cho những trường hợp như vậy, đã được thực hiện

db_query("INSERT IGNORE INTO ...")
if (!db_affected_rows()) {
  db_query("UPDATE ...");
}

Làm điều này vừa đơn giản vừa không có lỗi cho dù db đang ở tình trạng nào. Tùy chọn tốt nhất tôi có thể thấy ngay bây giờ, sẽ là xử lý nó bằng SQL và thực hiện điều này:

db_query("INSERT ... ON DUPLICATE KEY UPDATE");

Nhưng tôi đã hy vọng rằng API db sẽ có thể xử lý việc này.

Câu trả lời:


9

Thông tin đó được trả về trực tiếp bởi phương thức exec () của Delete / UpdateQuery, xem ví dụ: UpdateQuery :: exec () .

<?php
$affected = db_update('some_table')
  ->fields(array(
    'some_field' => $value,
  ))
  ->condition('another_field', $id)
  ->execute();
?>

insertQuery :: exec () trả về id chèn cuối cùng.


8

Sau khi đào xung quanh, tôi thấy rằng Drupal cung cấp một công cụ có tên sẵn sàng cho trường hợp sử dụng chính xác của tôi:

Chèn một hàng trong db hoặc cập nhật hiện có nếu nó đã có.

Đây được gọi là truy vấn hợp nhất , có thể được thực hiện nguyên tử cho một số công cụ db.

Nội dung khá đơn giản:

db_merge('example')
  ->key(array('name' => $name))
  ->fields(array(
    'field1' => $value1,
    'field2' => $value2,
))
->execute();

À đúng, đó là câu trả lời chính xác cho câu hỏi cập nhật của bạn :) Lưu ý rằng các truy vấn hợp nhất đã được thiết kế lại muộn trong chu kỳ phát triển D7 để thực sự hoạt động như các truy vấn sql MERGE, là một phần của tiêu chuẩn SQL 2003 nhưng chưa có dbms nào thực hiện nó , vì vậy tất cả các dbms yêu cầu hai truy vấn (chúng được tạo thành nguyên tử bằng cách sử dụng các giao dịch). Vấn đề với cách tiếp cận truy vấn duy nhất được sử dụng cho MySQL là nó hoàn toàn bỏ qua định nghĩa khóa () và chỉ đơn giản làm việc với các khóa duy nhất / chính của một bảng đã cho.
Berdir

@Berdir: Cảm ơn đã chỉ cho tôi đi đúng hướng. Tôi là một trong những nhà phát triển thích viết SQL và có một thời gian khó khăn để làm quen với API db mới :)
googletorp

Cảm ơn con trỏ này. Tuy nhiên, tôi đã phải dùng đến db_query dù sao vì api của Drupal không cho phép sử dụng các hằng số như CURRENT_TIMESTAMP (xem drupal.org/node/215821 )
Whiskey
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.