Fungsi SQLBulkOperations

Kesesuaian
Versi yang diperkenalkan: Kepatuhan standar ODBC 3.0: ODBC

Summary
SQLBulkOperations melakukan sisipan massal dan operasi bookmark massal, termasuk pembaruan, hapus, dan pengambilan berdasarkan bookmark.

Syntax

  
SQLRETURN SQLBulkOperations(  
     SQLHSTMT       StatementHandle,  
     SQLUSMALLINT   Operation);  

Arguments

StatementHandle
[Input] Handel pernyataan.

Operation
[Input] Operasi yang harus dilakukan:

SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK

Untuk informasi selengkapnya, lihat "Komentar."

Returns

SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR, atau SQL_INVALID_HANDLE.

Diagnostics

Ketika SQLBulkOperations mengembalikan SQL_ERROR atau SQL_SUCCESS_WITH_INFO, nilai SQLSTATE yang terkait dapat diperoleh dengan memanggil SQLGetDiagRec dengan HandleType SQL_HANDLE_STMT dan HandleStatementHandle. Tabel berikut mencantumkan nilai SQLSTATE yang biasanya dikembalikan oleh SQLBulkOperations dan menjelaskan masing-masing dalam konteks fungsi ini; notasi "(DM)" mendahului deskripsi SQLSTATE yang dikembalikan oleh Driver Manager. Kode pengembalian yang terkait dengan setiap nilai SQLSTATE SQL_ERROR, kecuali disebutkan sebaliknya.

Untuk semua SQLSTATE yang dapat mengembalikan SQL_SUCCESS_WITH_INFO atau SQL_ERROR (kecuali 01xxx SQLSTATE), SQL_SUCCESS_WITH_INFO dikembalikan jika terjadi kesalahan pada satu atau lebih, tetapi tidak semua, baris dari operasi multibaris, dan SQL_ERROR dikembalikan jika terjadi kesalahan pada operasi satu baris.

SQLSTATE Kesalahan Deskripsi
01000 Peringatan umum Pesan informasi khusus driver. (Fungsi mengembalikan SQL_SUCCESS_WITH_INFO.)
01004 Pemotongan kanan data string Argumen Operasi SQL_FETCH_BY_BOOKMARK, dan data string atau biner yang dikembalikan untuk kolom atau kolom dengan tipe data SQL_C_CHAR atau SQL_C_BINARY menghasilkan pemotongan data karakter non-blank atau non-NULL.
01S01 Kesalahan dalam baris Argumen Operasi SQL_ADD, dan terjadi kesalahan pada satu atau lebih baris saat melakukan operasi tetapi setidaknya satu baris berhasil ditambahkan. (Fungsi mengembalikan SQL_SUCCESS_WITH_INFO.)

(Kesalahan ini hanya muncul ketika aplikasi bekerja dengan ODBC 2. x driver.)
01S07 Pemotongan pecahan Argumen Operation SQL_FETCH_BY_BOOKMARK, tipe data dari buffer aplikasi tidak SQL_C_CHAR atau SQL_C_BINARY, dan data yang dikembalikan ke buffer aplikasi untuk satu atau lebih kolom dipotong. (Untuk tipe data numerik, bagian fraksional dari angka dipotong. Untuk tipe data waktu, timestamp, dan interval C yang mengandung komponen waktu, bagian fraksional dari waktu tersebut dipotong.)

(Fungsi mengembalikan SQL_SUCCESS_WITH_INFO.)
07006 Pelanggaran atribut jenis data terbatas Argumen Operation SQL_FETCH_BY_BOOKMARK, dan nilai data dari sebuah kolom dalam set hasil tidak dapat dikonversi ke tipe data yang ditentukan oleh argumen TargetType dalam pemanggilan SQLBindCol.

Argumen Operation adalah SQL_UPDATE_BY_BOOKMARK atau SQL_ADD, dan nilai data dalam buffer aplikasi tidak dapat dikonversi ke tipe data kolom dalam set hasil.
07009 Indeks deskriptor tidak valid Argumen Operasi adalah SQL_ADD, dan sebuah kolom diikat dengan nomor kolom yang lebih besar dari jumlah kolom dalam set hasil.
21S02 Tingkat tabel turunan tidak cocok dengan daftar kolom Argumen Operasi adalah SQL_UPDATE_BY_BOOKMARK; dan tidak ada kolom yang dapat diperbarui karena semua kolom tidak terikat atau hanya baca, atau nilai dalam buffer panjang/indikator yang terikat adalah SQL_COLUMN_IGNORE.
22001 Pemotongan kanan data string Penetapan karakter atau nilai biner pada kolom dalam set hasil menghasilkan pemotongan karakter atau byte yang tidak kosong (untuk karakter) atau non-null (untuk biner).
22003 Nilai numerik di luar rentang Argumen Operasi adalah SQL_ADD atau SQL_UPDATE_BY_BOOKMARK, dan penetapan nilai numerik pada kolom dalam set hasil menyebabkan seluruh bagian (bukan fraksional) dari angka dipotong.

Argumen Operasi adalah SQL_FETCH_BY_BOOKMARK, dan mengembalikan nilai numerik untuk satu atau lebih kolom terikat akan menyebabkan kehilangan digit signifikan.
22007 Format tanggalwaktu tidak valid Argumen Operasi bernilai SQL_ADD atau SQL_UPDATE_BY_BOOKMARK, dan penugasan nilai tanggal atau cap waktu ke kolom dalam set hasil menyebabkan bidang tahun, bulan, atau hari berada di luar rentang.

Argumen Operasi adalah SQL_FETCH_BY_BOOKMARK, dan mengembalikan nilai tanggal atau cap waktu untuk satu atau lebih kolom terikat akan menyebabkan kolom tahun, bulan, atau hari berada di luar jangkauan.
22008 Lompatan bidang tanggal/waktu Argumen Operasi bernilai SQL_ADD atau SQL_UPDATE_BY_BOOKMARK, dan kinerja aritmetika datetime pada data yang dikirim ke kolom dalam set hasil menghasilkan field datetime (kolom tahun, bulan, hari, jam, menit, atau kedua) dari hasil yang berada di luar rentang nilai yang diizinkan untuk field tersebut atau tidak valid berdasarkan aturan alami kalender Gregorian untuk datetime.

Argumen Operasi SQL_FETCH_BY_BOOKMARK, dan kinerja aritmetika datetime pada data yang diambil dari set hasil menghasilkan field datetime (kolom tahun, bulan, hari, jam, menit, atau kedua) dari hasil yang berada di luar rentang nilai yang diizinkan untuk field tersebut atau menjadi tidak valid berdasarkan aturan alami kalender Gregorian untuk datetime.
22015 Meluapnya bidang interval Argumen Operasi adalah SQL_ADD atau SQL_UPDATE_BY_BOOKMARK, dan penugasan tipe numerik atau interval C yang tepat ke tipe data interval SQL menyebabkan kehilangan digit yang signifikan.

Argumen Operasi adalah SQL_ADD atau SQL_UPDATE_BY_BOOKMARK; saat menetapkan ke tipe interval SQL, tidak ada representasi nilai tipe C dalam tipe interval SQL.

Argumen Operasi SQL_FETCH_BY_BOOKMARK, dan menetapkan dari tipe SQL numerik atau interval yang tepat ke tipe interval C menyebabkan hilangnya digit signifikan di kolom awal.

Argumen Operasi SQL_FETCH_BY_BOOKMARK; saat menetapkan tipe C interval, tidak ada representasi nilai tipe SQL dalam tipe C interval.
22018 Nilai karakter tidak valid untuk spesifikasi cast Argumen Operasi SQL_FETCH_BY_BOOKMARK; tipe C adalah numerik tepat atau perkiraan, data datetime, atau interval; tipe SQL pada kolom tersebut adalah tipe data karakter; dan nilai dalam kolom tersebut bukanlah literal valid dari tipe C yang terikat.

Argumen Operasi adalah SQL_ADD atau SQL_UPDATE_BY_BOOKMARK; tipe SQL adalah tipe data data tepat atau perkiraan, datetime, atau interval; tipe C adalah SQL_C_CHAR; dan nilai di kolom bukanlah literal valid dari tipe SQL yang terikat.
23000 Pelanggaran batasan integritas Argumen Operasi adalah SQL_ADD, SQL_DELETE_BY_BOOKMARK, atau SQL_UPDATE_BY_BOOKMARK, dan sebuah batasan integritas dilanggar.

Argumen Operation SQL_ADD, dan kolom yang tidak terikat didefinisikan sebagai NOT NULL dan tidak memiliki default.

Argumen Operation SQL_ADD, panjang yang ditentukan dalam buffer StrLen_or_IndPtr terikat adalah SQL_COLUMN_IGNORE, dan kolom tidak memiliki nilai default.
24000 Status kursor tidak valid StatementHandle berada dalam status eksekusi, tetapi tidak ada set hasil yang terkait dengan StatementHandle tersebut.
40001 Kegagalan serialisasi Transaksi digulung balik karena kebuntuan sumber daya dengan transaksi lain.
40003 Penyelesaian pernyataan tidak diketahui Koneksi terkait gagal selama eksekusi fungsi ini, dan status transaksi tidak dapat ditentukan.
42000 Kesalahan sintaks atau pelanggaran akses Driver tidak dapat mengunci baris sesuai kebutuhan untuk melakukan operasi yang diminta dalam argumen Operasi .
44000 DENGAN PELANGGARAN OPSI PEMERIKSAAN Argumen Operasi adalah SQL_ADD atau SQL_UPDATE_BY_BOOKMARK, dan sisipan atau pembaruan dilakukan pada tabel yang telah dilihat (atau tabel yang diturunkan dari tabel yang telah dilihat) yang dibuat dengan menentukan OPSI DENGAN CHECK, sedemikian rupa sehingga satu atau lebih baris yang terpengaruh oleh sisipan atau pembaruan tidak lagi hadir dalam tabel yang telah dilihat.
HY000 Kesalahan umum Terjadi kesalahan yang tidak ada SQLSTATE tertentu dan tidak ada SQLSTATE khusus implementasi yang ditentukan. Pesan kesalahan yang dikembalikan oleh SQLGetDiagRec di buffer *MessageText menjelaskan kesalahan dan penyebabnya.
HY001 Kesalahan alokasi memori Driver tidak dapat mengalokasikan memori yang diperlukan untuk mendukung eksekusi atau penyelesaian fungsi.
HY008 Operasi dibatalkan Pemrosesan asinkron diaktifkan untuk StatementHandle. Fungsi ini dipanggil, dan sebelum selesai dieksekusi, SQLCancel atau SQLCancelHandle dipanggil pada StatementHandle. Kemudian fungsi dipanggil lagi pada StatementHandle.

Fungsi ini dipanggil, dan sebelum selesai dieksekusi, SQLCancel atau SQLCancelHandle dipanggil pada StatementHandle dari utas yang berbeda dalam aplikasi multithread.
HY010 Kesalahan urutan fungsi (DM) Fungsi eksekusi asinkron dipanggil untuk handel koneksi yang terkait dengan StatementHandle. Fungsi asinkron ini masih berjalan saat fungsi SQLBulkOperations dipanggil.

(DM) SQLExecute, SQLExecDirect, atau SQLMoreResults dipanggil untuk StatementHandle dan dikembalikan SQL_PARAM_DATA_AVAILABLE. Fungsi ini dipanggil sebelum data diambil untuk semua parameter yang dialirkan.

(DM) StatementHandle yang ditentukan tidak dalam keadaan eksekusi. Fungsi ini dipanggil tanpa terlebih dahulu memanggil SQLExecDirect, SQLExecute, atau fungsi katalog.

(DM) Fungsi eksekusi asinkron (bukan yang ini) dipanggil untuk StatementHandle dan masih dijalankan ketika fungsi ini dipanggil.

(DM) SQLExecute, SQLExecDirect, atau SQLSetPos dipanggil untuk StatementHandle dan mengembalikan SQL_NEED_DATA. Fungsi ini dipanggil sebelum data dikirim untuk semua parameter atau kolom data-at-execution.

(DM) Sopirnya adalah ODBC 2. x driver, dan SQLBulkOperations dipanggil untuk StatementHandle sebelum SQLFetchScroll atau SQLFetch dipanggil.

(DM) SQLBulkOperations dipanggil setelah SQLExtendedFetch dipanggil pada StatementHandle.
HY011 Atribut tidak dapat diatur sekarang (DM) Sopirnya adalah ODBC 2. x driver, dan atribut pernyataan SQL_ATTR_ROW_STATUS_PTR diatur antara pemanggilan ke SQLFetch atau SQLFetchScroll dan SQLBulkOperations.
HY013 Kesalahan manajemen memori Panggilan fungsi tidak dapat diproses karena objek memori yang mendasar tidak dapat diakses, mungkin karena kondisi memori yang rendah.
HY090 String atau panjang buffer tidak valid Argumen Operasi adalah SQL_ADD atau SQL_UPDATE_BY_BOOKMARK; Nilai data bukanlah null pointer; tipe data C adalah SQL_C_BINARY atau SQL_C_CHAR; dan nilai panjang kolom kurang dari 0, tetapi tidak sama dengan SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NTS, atau SQL_NULL_DATA, atau kurang dari atau sama dengan SQL_LEN_DATA_AT_EXEC_OFFSET.

Nilai dalam buffer panjang/indikator adalah SQL_DATA_AT_EXEC; tipe SQL adalah tipe data SQL_LONGVARCHAR, SQL_LONGVARBINARY, atau data spesifik sumber data panjang; dan tipe informasi SQL_NEED_LONG_DATA_LEN di SQLGetInfo adalah "Y".

Argumen Operation SQL_ADD, atribut pernyataan SQL_ATTR_USE_BOOKMARK diatur ke SQL_UB_VARIABLE, dan kolom 0 diikat ke buffer yang panjangnya tidak sama dengan panjang maksimum bookmark untuk hasil set ini. (Panjang ini tersedia di bidang SQL_DESC_OCTET_LENGTH IRD dan dapat diperoleh dengan memanggil SQLDescribeCol, SQLColAttribute, atau SQLGetDescField.)
HY092 Pengenal atribut tidak valid (DM) Nilai yang ditentukan untuk argumen Operasi tidak valid.

Argumen Operasi adalah SQL_ADD, SQL_UPDATE_BY_BOOKMARK, atau SQL_DELETE_BY_BOOKMARK, dan atribut pernyataan SQL_ATTR_CONCURRENCY diatur ke SQL_CONCUR_READ_ONLY.

Argumen Operation adalah SQL_DELETE_BY_BOOKMARK, SQL_FETCH_BY_BOOKMARK, atau SQL_UPDATE_BY_BOOKMARK, dan kolom bookmark tidak terikat atau atribut pernyataan SQL_ATTR_USE_BOOKMARKS diatur ke SQL_UB_OFF.
HY117 Koneksi ditangguhkan karena status transaksi yang tidak diketahui. Hanya fungsi putuskan sambungan dan baca-saja yang diizinkan. (DM) Untuk informasi selengkapnya tentang status ditangguhkan, lihat Fungsi SQLEndTran.
HYC00 Fitur opsional tidak diimplementasikan Driver atau sumber data tidak mendukung operasi yang diminta dalam argumen Operasi .
HYT00 Waktu tunggu habis Periode batas waktu kueri kedaluwarsa sebelum sumber data mengembalikan tataan hasil. Periode timeout diatur melalui SQLSetStmtAttr dengan argumen Attribute sebesar SQL_ATTR_QUERY_TIMEOUT.
HYT01 Waktu tunggu koneksi habis Periode batas waktu koneksi kedaluwarsa sebelum sumber data merespons permintaan. Periode batas waktu koneksi diatur melalui SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT.
IM001 Driver tidak mendukung fungsi ini (DM) Driver yang terkait dengan StatementHandle tidak mendukung fungsi.
IM017 Polling dinonaktifkan dalam mode pemberitahuan asinkron Setiap kali model pemberitahuan digunakan, polling dinonaktifkan.
IM018 SQLCompleteAsync belum dipanggil untuk menyelesaikan operasi asinkron sebelumnya pada handel ini. Jika panggilan fungsi sebelumnya pada handel mengembalikan SQL_STILL_EXECUTING dan jika mode pemberitahuan diaktifkan, SQLCompleteAsync harus dipanggil pada handel untuk melakukan pasca-pemrosesan dan menyelesaikan operasi.

Komentar

Caution

Untuk informasi tentang pernyataan apa yang dapat dipanggil SQLBulkOperations dan apa yang harus dilakukan untuk kompatibilitas dengan ODBC 2. x aplikasi, lihat bagian Block Cursors, Scrollable Cursors, dan Backward Compatibility di Lampiran G: Pedoman Driver untuk Kompatibilitas Mundur.

Sebuah aplikasi menggunakan SQLBulkOperations untuk melakukan operasi berikut pada tabel atau tampilan dasar yang sesuai dengan kueri saat ini:

  • Tambahkan baris baru.

  • Perbarui satu set baris di mana setiap baris diidentifikasi dengan bookmark.

  • Hapus satu set baris di mana setiap baris diidentifikasi dengan bookmark.

  • Ambil satu set baris di mana setiap baris diidentifikasi dengan bookmark.

Setelah pemanggilan ke SQLBulkOperations, posisi kursor blok tidak terdefinisi. Aplikasi harus memanggil SQLFetchScroll untuk mengatur posisi kursor. Sebuah aplikasi sebaiknya memanggil SQLFetchScroll hanya dengan argumen FetchOrientation SQL_FETCH_FIRST, SQL_FETCH_LAST, SQL_FETCH_ABSOLUTE, atau SQL_FETCH_BOOKMARK. Posisi kursor tidak terdefinisi jika aplikasi memanggil SQLFetch atau SQLFetchScroll dengan argumen FetchOrientation SQL_FETCH_PRIOR, SQL_FETCH_NEXT, atau SQL_FETCH_RELATIVE.

Sebuah kolom dapat diabaikan dalam operasi massal yang dilakukan oleh pemanggilan ke SQLBulkOperations dengan mengatur buffer panjang/indikator kolom yang ditentukan dalam panggilan ke SQLBindCol, menjadi SQL_COLUMN_IGNORE.

Tidak perlu aplikasi mengatur atribut pernyataan SQL_ATTR_ROW_OPERATION_PTR saat memanggil SQLBulkOperations karena baris tidak dapat diabaikan saat melakukan operasi massal dengan fungsi ini.

Buffer yang ditunjuk oleh atribut pernyataan SQL_ATTR_ROWS_FETCHED_PTR berisi jumlah baris yang terpengaruh oleh pemanggilan ke SQLBulkOperations.

Ketika argumen Operasi SQL_ADD atau SQL_UPDATE_BY_BOOKMARK dan daftar select-list dari spesifikasi kueri yang terkait dengan kursor berisi lebih dari satu referensi ke kolom yang sama, maka didefinisikan oleh driver apakah kesalahan dihasilkan atau driver mengabaikan referensi duplikat dan melakukan operasi yang diminta.

Untuk informasi lebih lanjut tentang cara menggunakan SQLBulkOperations, lihat Memperbarui Data dengan SQLBulkOperations.

Melakukan Insert Massal

Untuk menyisipkan data dengan SQLBulkOperations, sebuah aplikasi melakukan urutan langkah berikut:

  1. Menjalankan kueri yang mengembalikan set hasil.

  2. Mengatur atribut pernyataan SQL_ATTR_ROW_ARRAY_SIZE ke jumlah baris yang ingin disisipkan.

  3. Memanggil SQLBindCol untuk mengikat data yang ingin disisipkan. Data terikat pada array dengan ukuran sama dengan nilai SQL_ATTR_ROW_ARRAY_SIZE.

    Note

    Ukuran array yang ditunjuk oleh atribut pernyataan SQL_ATTR_ROW_STATUS_PTR harus sama dengan SQL_ATTR_ROW_ARRAY_SIZE atau SQL_ATTR_ROW_STATUS_PTR harus berupa null pointer.

  4. Memanggil SQLBulkOperations (StatementHandle, SQL_ADD) untuk melakukan penyisipan.

  5. Jika aplikasi telah mengatur atribut pernyataan SQL_ATTR_ROW_STATUS_PTR, aplikasi dapat memeriksa array ini untuk melihat hasil operasi.

Jika sebuah aplikasi mengikat kolom 0 sebelum memanggil SQLBulkOperations dengan argumen Operation sebesar SQL_ADD, driver akan memperbarui buffer kolom 0 yang terikat dengan nilai bookmark untuk baris yang baru dimasukkan. Agar hal ini terjadi, aplikasi harus telah mengatur atribut pernyataan SQL_ATTR_USE_BOOKMARKS ke SQL_UB_VARIABLE sebelum menjalankan pernyataan tersebut. (Ini tidak berlaku dengan ODBC 2. x driver.)

Data panjang dapat ditambahkan secara bertahap oleh SQLBulkOperations, dengan menggunakan panggilan ke SQLParamData dan SQLPutData. Untuk informasi lebih lanjut, lihat "Menyediakan Data Panjang untuk Sisipan dan Pembaruan Massal" di bagian selanjutnya dalam referensi fungsi ini.

Tidak perlu aplikasi memanggil SQLFetch atau SQLFetchScroll sebelum memanggil SQLBulkOperations (kecuali saat melawan ODBC 2).x driver; lihat Kompatibilitas Mundur dan Kepatuhan Standar).

Perilaku ini didefinisikan oleh driver jika SQLBulkOperations, dengan argumen Operation SQL_ADD, dipanggil pada kursor yang berisi kolom duplikat. Driver dapat mengembalikan SQLSTATE yang didefinisikan oleh driver, menambahkan data ke kolom pertama yang muncul dalam set hasil, atau melakukan perilaku lain yang didefinisikan oleh driver.

Melakukan Pembaruan Masal dengan Menggunakan Bookmark

Untuk melakukan pembaruan massal menggunakan bookmark dengan SQLBulkOperations, sebuah aplikasi melakukan langkah-langkah berikut secara berurutan:

  1. Mengatur atribut pernyataan SQL_ATTR_USE_BOOKMARKS ke SQL_UB_VARIABLE.

  2. Menjalankan kueri yang mengembalikan set hasil.

  3. Mengatur atribut pernyataan SQL_ATTR_ROW_ARRAY_SIZE ke jumlah baris yang ingin diperbarui.

  4. Memanggil SQLBindCol untuk mengikat data yang ingin diperbarui. Data terikat pada array dengan ukuran sama dengan nilai SQL_ATTR_ROW_ARRAY_SIZE. Aplikasi ini juga memanggil SQLBindCol untuk mengikat kolom 0 (kolom bookmark).

  5. Menyalin bookmark untuk baris yang ingin diperbarui ke array yang terikat pada kolom 0.

  6. Memperbarui data di buffer yang terikat.

    Note

    Ukuran array yang ditunjuk oleh atribut pernyataan SQL_ATTR_ROW_STATUS_PTR harus sama dengan SQL_ATTR_ROW_ARRAY_SIZE atau SQL_ATTR_ROW_STATUS_PTR harus berupa null pointer.

  7. Memanggil SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK).

    Note

    Jika aplikasi telah mengatur atribut pernyataan SQL_ATTR_ROW_STATUS_PTR, aplikasi dapat memeriksa array ini untuk melihat hasil operasi.

  8. Secara opsional memanggil SQLBulkOperations (StatementHandle, SQL_FETCH_BY_BOOKMARK) untuk mengambil data ke buffer aplikasi yang terikat guna memverifikasi bahwa pembaruan telah terjadi.

  9. Jika data telah diperbarui, driver mengubah nilai dalam array status baris untuk baris yang sesuai menjadi SQL_ROW_UPDATED.

Pembaruan massal yang dilakukan oleh SQLBulkOperations dapat mencakup data panjang dengan menggunakan panggilan ke SQLParamData dan SQLPutData. Untuk informasi lebih lanjut, lihat "Menyediakan Data Panjang untuk Sisipan dan Pembaruan Massal" di bagian selanjutnya dalam referensi fungsi ini.

Jika bookmark tetap ada di kursor, aplikasi tidak perlu memanggil SQLFetch atau SQLFetchScroll sebelum memperbarui dengan bookmark. Aplikasi ini dapat menggunakan bookmark yang disimpan dari kursor sebelumnya. Jika bookmark tidak tetap ada di seluruh kursor, aplikasi harus memanggil SQLFetch atau SQLFetchScroll untuk mengambil bookmark.

Perilaku ini didefinisikan oleh driver jika SQLBulkOperations, dengan argumen Operation SQL_UPDATE_BY_BOOKMARK, dipanggil pada kursor yang berisi kolom duplikat. Driver dapat mengembalikan SQLSTATE yang didefinisikan oleh driver, memperbarui kolom pertama yang muncul dalam set hasil, atau melakukan perilaku lain yang didefinisikan oleh driver.

Melakukan pengambilan massal menggunakan bookmark

Untuk melakukan pengambilan massal menggunakan bookmark dengan SQLBulkOperations, sebuah aplikasi melakukan langkah-langkah berikut secara berurutan:

  1. Mengatur atribut pernyataan SQL_ATTR_USE_BOOKMARKS ke SQL_UB_VARIABLE.

  2. Menjalankan kueri yang mengembalikan set hasil.

  3. Mengatur atribut pernyataan SQL_ATTR_ROW_ARRAY_SIZE ke jumlah baris yang ingin diambil.

  4. Memanggil SQLBindCol untuk mengikat data yang ingin diambil. Data terikat pada array dengan ukuran sama dengan nilai SQL_ATTR_ROW_ARRAY_SIZE. Aplikasi ini juga memanggil SQLBindCol untuk mengikat kolom 0 (kolom bookmark).

  5. Menyalin bookmark untuk baris yang ingin diambil ke array yang terikat pada kolom 0. (Ini mengasumsikan bahwa aplikasi sudah memperoleh bookmark secara terpisah.)

    Note

    Ukuran array yang ditunjuk oleh atribut pernyataan SQL_ATTR_ROW_STATUS_PTR harus sama dengan SQL_ATTR_ROW_ARRAY_SIZE atau SQL_ATTR_ROW_STATUS_PTR harus berupa null pointer.

  6. Memanggil SQLBulkOperations (StatementHandle, SQL_FETCH_BY_BOOKMARK).

  7. Jika aplikasi telah mengatur atribut pernyataan SQL_ATTR_ROW_STATUS_PTR, aplikasi dapat memeriksa array ini untuk melihat hasil operasi.

Jika bookmark tetap ada di seluruh kursor, aplikasi tidak perlu memanggil SQLFetch atau SQLFetchScroll sebelum diambil oleh bookmark. Aplikasi ini dapat menggunakan bookmark yang disimpan dari kursor sebelumnya. Jika bookmark tidak tetap ada di seluruh kursor, aplikasi harus memanggil SQLFetch atau SQLFetchScroll satu kali untuk mengambil bookmark.

Melakukan Penghapusan Masal Menggunakan Bookmark

Untuk melakukan penghapusan massal menggunakan bookmark dengan SQLBulkOperations, sebuah aplikasi melakukan langkah-langkah berikut secara berurutan:

  1. Mengatur atribut pernyataan SQL_ATTR_USE_BOOKMARKS ke SQL_UB_VARIABLE.

  2. Menjalankan kueri yang mengembalikan set hasil.

  3. Mengatur atribut pernyataan SQL_ATTR_ROW_ARRAY_SIZE ke jumlah baris yang ingin dihapus.

  4. Memanggil SQLBindCol untuk mengikat kolom 0 (kolom bookmark).

  5. Menyalin bookmark untuk baris yang ingin dihapus ke dalam array yang terikat pada kolom 0.

    Note

    Ukuran array yang ditunjuk oleh atribut pernyataan SQL_ATTR_ROW_STATUS_PTR harus sama dengan SQL_ATTR_ROW_ARRAY_SIZE atau SQL_ATTR_ROW_STATUS_PTR harus berupa null pointer.

  6. Memanggil SQLBulkOperations (StatementHandle, SQL_DELETE_BY_BOOKMARK).

  7. Jika aplikasi telah mengatur atribut pernyataan SQL_ATTR_ROW_STATUS_PTR, aplikasi dapat memeriksa array ini untuk melihat hasil operasi.

Jika bookmark tetap ada di seluruh kursor, aplikasi tidak perlu memanggil SQLFetch atau SQLFetchScroll sebelum menghapus bookmark. Aplikasi ini dapat menggunakan bookmark yang disimpan dari kursor sebelumnya. Jika bookmark tidak tetap ada di seluruh kursor, aplikasi harus memanggil SQLFetch atau SQLFetchScroll satu kali untuk mengambil bookmark.

Menyediakan Data Panjang untuk Insert dan Pembaruan Massal

Data panjang dapat disediakan untuk sisipan massal dan pembaruan yang dilakukan melalui pemanggilan ke SQLBulkOperations. Untuk menyisipkan atau memperbarui data panjang, sebuah aplikasi melakukan langkah-langkah berikut selain langkah-langkah yang dijelaskan dalam bagian "Melakukan Bulk Inserts" dan "Melakukan Pembaruan Masal Menggunakan Bookmark" di awal topik ini.

  1. Ketika mengikat data menggunakan SQLBindCol, aplikasi menempatkan nilai yang didefinisikan aplikasi, seperti nomor kolom, di buffer *TargetValuePtr untuk kolom data-at-execution. Nilai tersebut dapat digunakan nanti untuk mengidentifikasi kolom.

    Aplikasi menempatkan hasil makro SQL_LEN_DATA_AT_EXEC(length) ke dalam buffer *StrLen_or_IndPtr . Jika tipe data SQL pada kolom adalah SQL_LONGVARBINARY, SQL_LONGVARCHAR, atau tipe data spesifik sumber data panjang dan driver mengembalikan "Y" untuk tipe informasi SQL_NEED_LONG_DATA_LEN di SQLGetInfo, panjang adalah jumlah byte data yang akan dikirim untuk parameter tersebut; jika tidak, nilainya harus tidak negatif dan diabaikan.

  2. Ketika SQLBulkOperations dipanggil, jika ada kolom data-at-execution, fungsi mengembalikan SQL_NEED_DATA dan melanjutkan ke langkah 3, yang mengikuti ini. (Jika tidak ada kolom data-saat-eksekusi, proses selesai.)

  3. Aplikasi memanggil SQLParamData untuk mengambil alamat buffer *TargetValuePtr untuk kolom data-at-execution pertama yang akan diproses. SQLParamData mengembalikan SQL_NEED_DATA. Aplikasi mengambil nilai yang didefinisikan aplikasi dari buffer *TargetValuePtr .

    Note

    Meskipun parameter data-at-execution menyerupai kolom data-at-execution, nilai yang dikembalikan oleh SQLParamData berbeda untuk masing-masing.

    Kolom data-at-execution adalah kolom dalam satu set baris yang datanya akan dikirim bersama SQLPutData ketika sebuah baris diperbarui atau dimasukkan dengan SQLBulkOperations. Mereka terikat dengan SQLBindCol. Nilai yang dikembalikan oleh SQLParamData adalah alamat baris dalam buffer *TargetValuePtr yang sedang diproses.

  4. Aplikasi memanggil SQLPutData satu atau beberapa kali untuk mengirim data untuk kolom tersebut. Lebih dari satu panggilan diperlukan jika semua nilai data tidak dapat dikembalikan dalam buffer *TargetValuePtr yang ditentukan di SQLPutData; beberapa panggilan ke SQLPutData untuk kolom yang sama hanya diperbolehkan saat mengirim data karakter C ke kolom dengan tipe data spesifik karakter, biner, atau sumber data, atau saat mengirim data biner C ke kolom dengan tipe data spesifik karakter, biner, atau sumber data.

  5. Aplikasi memanggil SQLParamData lagi untuk memberi sinyal bahwa semua data telah dikirim ke kolom tersebut.

    • Jika ada lebih banyak kolom data-saat-eksekusi, SQLParamData mengembalikan SQL_NEED_DATA dan alamat buffer TargetValuePtr untuk kolom data-saat-eksekusi berikutnya yang akan diproses. Aplikasi mengulangi langkah 4 dan 5.

    • Jika tidak ada lagi kolom data-saat-eksekusi, proses selesai. Jika pernyataan berhasil dieksekusi, SQLParamData mengembalikan SQL_SUCCESS atau SQL_SUCCESS_WITH_INFO; Jika eksekusi gagal, maka akan kembali SQL_ERROR. Pada titik ini, SQLParamData dapat mengembalikan SQLSTATE apa pun yang dapat dikembalikan oleh SQLBulkOperations.

Jika operasi dibatalkan atau terjadi kesalahan di SQLParamData atau SQLPutData setelah SQLBulkOperations mengembalikan SQL_NEED_DATA dan sebelum data dikirim untuk semua kolom data-saat-eksekusi, aplikasi hanya dapat memanggil SQLCancel, SQLGetDiagField, SQLGetDiagRec, SQLGetFunctions, SQLParamData, atau SQLPutData untuk pernyataan atau koneksi yang terkait dengan pernyataan tersebut. Jika memanggil fungsi lain untuk pernyataan atau koneksi yang terkait dengan pernyataan tersebut, fungsi akan mengembalikan SQL_ERROR dan SQLSTATE HY010 (Function sequence error).

Jika aplikasi memanggil SQLCancel saat driver masih membutuhkan data untuk kolom data-at-execution, driver akan membatalkan operasi tersebut. Aplikasi kemudian dapat memanggil SQLBulkOperations lagi; Pembatalan tidak memengaruhi status kursor atau posisi kursor saat ini.

Status Baris Array

Array status baris berisi nilai status untuk setiap baris data dalam rowset setelah pemanggilan SQLBulkOperations. Driver mengatur nilai status dalam array ini setelah pemanggilan ke SQLFetch, SQLFetchScroll, SQLSetPos, atau SQLBulkOperations. Array ini awalnya diisi oleh panggilan ke SQLBulkOperations jika SQLFetch atau SQLFetchScroll belum dipanggil sebelum SQLBulkOperations. Array ini ditunjuk oleh atribut pernyataan SQL_ATTR_ROW_STATUS_PTR. Jumlah elemen dalam array status baris harus sama dengan jumlah baris dalam rowset (sebagaimana didefinisikan oleh atribut pernyataan SQL_ATTR_ROW_ARRAY_SIZE). Untuk informasi tentang array status baris ini, lihat SQLFetch.

Contoh Kode

Contoh berikut mengambil 10 baris data sekaligus dari tabel Customers. Kemudian akan meminta pengguna untuk melakukan tindakan. Untuk mengurangi lalu lintas jaringan, buffer contoh akan memperbarui, menghapus, dan menyisipkan secara lokal dalam array yang terikat, tetapi pada offset melewati data rowset. Ketika pengguna memilih untuk mengirim pembaruan, penghapusan, dan sisipan ke sumber data, kode mengatur offset binding dengan tepat dan memanggil SQLBulkOperations. Untuk memudahkan, pengguna tidak dapat menyimpan buffer lebih dari 10 pembaruan, penghapusan, atau sisipan.

// SQLBulkOperations_Function.cpp  
// compile with: ODBC32.lib  
#include <windows.h>  
#include <sqlext.h>  
#include "stdio.h"  
  
#define UPDATE_ROW 100  
#define DELETE_ROW 101  
#define ADD_ROW 102  
#define SEND_TO_DATA_SOURCE 103  
#define UPDATE_OFFSET 10  
#define INSERT_OFFSET 20  
#define DELETE_OFFSET 30  
  
// Define structure for customer data (assume 10 byte maximum bookmark size).  
typedef struct tagCustStruct {  
   SQLCHAR Bookmark[10];  
   SQLINTEGER BookmarkLen;  
   SQLUINTEGER CustomerID;  
   SQLINTEGER CustIDInd;  
   SQLCHAR CompanyName[51];  
   SQLINTEGER NameLenOrInd;  
   SQLCHAR Address[51];  
   SQLINTEGER AddressLenOrInd;  
   SQLCHAR Phone[11];  
   SQLINTEGER PhoneLenOrInd;  
} CustStruct;  
  
// Allocate 40 of these structures. Elements 0-9 are for the current rowset,  
// elements 10-19 are for the buffered updates, elements 20-29 are for  
// the buffered inserts, and elements 30-39 are for the buffered deletes.  
CustStruct CustArray[40];  
SQLUSMALLINT RowStatusArray[10], Action, RowNum, NumUpdates = 0, NumInserts = 0,  
NumDeletes = 0;  
SQLLEN BindOffset = 0;  
SQLRETURN retcode;  
SQLHENV henv = NULL;  
SQLHDBC hdbc = NULL;  
SQLHSTMT hstmt = NULL;  
  
int main() {  
   retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);  
   retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);   
  
   retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);   
   retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);  
  
   retcode = SQLConnect(hdbc, (SQLCHAR*) "Northwind", SQL_NTS, (SQLCHAR*) NULL, 0, NULL, 0);  
   retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);  
  
   // Set the following statement attributes:  
   // SQL_ATTR_CURSOR_TYPE:           Keyset-driven  
   // SQL_ATTR_ROW_BIND_TYPE:         Row-wise  
   // SQL_ATTR_ROW_ARRAY_SIZE:        10  
   // SQL_ATTR_USE_BOOKMARKS:         Use variable-length bookmarks  
   // SQL_ATTR_ROW_STATUS_PTR:        Points to RowStatusArray  
   // SQL_ATTR_ROW_BIND_OFFSET_PTR:   Points to BindOffset  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER)sizeof(CustStruct), 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_USE_BOOKMARKS, (SQLPOINTER)SQL_UB_VARIABLE, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_OFFSET_PTR, &BindOffset, 0);  
  
   // Bind arrays to the bookmark, CustomerID, CompanyName, Address, and Phone columns.  
   retcode = SQLBindCol(hstmt, 0, SQL_C_VARBOOKMARK, CustArray[0].Bookmark, sizeof(CustArray[0].Bookmark), &CustArray[0].BookmarkLen);  
   retcode = SQLBindCol(hstmt, 1, SQL_C_ULONG, &CustArray[0].CustomerID, 0, &CustArray[0].CustIDInd);  
   retcode = SQLBindCol(hstmt, 2, SQL_C_CHAR, CustArray[0].CompanyName, sizeof(CustArray[0].CompanyName), &CustArray[0].NameLenOrInd);  
   retcode = SQLBindCol(hstmt, 3, SQL_C_CHAR, CustArray[0].Address, sizeof(CustArray[0].Address), &CustArray[0].AddressLenOrInd);  
   retcode = SQLBindCol(hstmt, 4, SQL_C_CHAR, CustArray[0].Phone, sizeof(CustArray[0].Phone), &CustArray[0].PhoneLenOrInd);  
  
   // Execute a statement to retrieve rows from the Customers table.  
   retcode = SQLExecDirect(hstmt, (SQLCHAR*)"SELECT CustomerID, CompanyName, Address, Phone FROM Customers", SQL_NTS);  
  
   // Fetch and display the first 10 rows.  
   retcode = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0);  
   // DisplayCustData(CustArray, 10);  
  
   // Call GetAction to get an action and a row number from the user.  
   // while (GetAction(&Action, &RowNum)) {  
   Action = SQL_FETCH_NEXT;  
   RowNum = 2;  
   switch (Action) {  
      case SQL_FETCH_NEXT:  
      case SQL_FETCH_PRIOR:  
      case SQL_FETCH_FIRST:  
      case SQL_FETCH_LAST:  
      case SQL_FETCH_ABSOLUTE:  
      case SQL_FETCH_RELATIVE:  
         // Fetch and display the requested data.  
         SQLFetchScroll(hstmt, Action, RowNum);  
         // DisplayCustData(CustArray, 10);  
         break;  
  
      case UPDATE_ROW:  
         // Check if we have reached the maximum number of buffered updates.  
         if (NumUpdates < 10) {  
            // Get the new customer data and place it in the next available element of  
            // the buffered updates section of CustArray, copy the bookmark of the row  
            // being updated to the same element, and increment the update counter.  
            // Checking to see we have not already buffered an update for this  
            // row not shown.  
            // GetNewCustData(CustArray, UPDATE_OFFSET + NumUpdates);  
            memcpy(CustArray[UPDATE_OFFSET + NumUpdates].Bookmark,  
               CustArray[RowNum - 1].Bookmark,  
               CustArray[RowNum - 1].BookmarkLen);  
            CustArray[UPDATE_OFFSET + NumUpdates].BookmarkLen =  
               CustArray[RowNum - 1].BookmarkLen;  
            NumUpdates++;  
         } else {  
            printf("Buffers full. Send buffered changes to the data source.");  
         }  
         break;  
      case DELETE_ROW:  
         // Check if we have reached the maximum number of buffered deletes.  
         if (NumDeletes < 10) {  
            // Copy the bookmark of the row being deleted to the next available element  
            // of the buffered deletes section of CustArray and increment the delete  
            // counter. Checking to see we have not already buffered an update for  
            // this row not shown.  
            memcpy(CustArray[DELETE_OFFSET + NumDeletes].Bookmark,  
               CustArray[RowNum - 1].Bookmark,  
               CustArray[RowNum - 1].BookmarkLen);  
  
            CustArray[DELETE_OFFSET + NumDeletes].BookmarkLen =  
               CustArray[RowNum - 1].BookmarkLen;  
  
            NumDeletes++;  
         } else  
            printf("Buffers full. Send buffered changes to the data source.");  
         break;  
  
      case ADD_ROW:  
         // reached maximum number of buffered inserts?  
         if (NumInserts < 10) {  
            // Get the new customer data and place it in the next available element of  
            // the buffered inserts section of CustArray and increment insert counter.  
            // GetNewCustData(CustArray, INSERT_OFFSET + NumInserts);  
            NumInserts++;  
         } else  
            printf("Buffers full. Send buffered changes to the data source.");  
         break;  
  
      case SEND_TO_DATA_SOURCE:  
         // If there are any buffered updates, inserts, or deletes, set the array size  
         // to that number, set the binding offset to use the data in the buffered  
         // update, insert, or delete part of CustArray, and call SQLBulkOperations to  
         // do the updates, inserts, or deletes. Because we will never have more than  
         // 10 updates, inserts, or deletes, we can use the same row status array.  
         if (NumUpdates) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumUpdates, 0);  
            BindOffset = UPDATE_OFFSET * sizeof(CustStruct);  
            SQLBulkOperations(hstmt, SQL_UPDATE_BY_BOOKMARK);  
            NumUpdates = 0;  
         }  
  
         if (NumInserts) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumInserts, 0);  
            BindOffset = INSERT_OFFSET * sizeof(CustStruct);  
            SQLBulkOperations(hstmt, SQL_ADD);  
            NumInserts = 0;  
         }  
  
         if (NumDeletes) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumDeletes, 0);  
            BindOffset = DELETE_OFFSET * sizeof(CustStruct);  
            SQLBulkOperations(hstmt, SQL_DELETE_BY_BOOKMARK);  
            NumDeletes = 0;  
         }  
  
         // If there were any updates, inserts, or deletes, reset the binding offset  
         // and array size to their original values.  
         if (NumUpdates || NumInserts || NumDeletes) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);  
            BindOffset = 0;  
         }  
         break;  
   }  
   // }  
  
   // Close the cursor.  
   SQLFreeStmt(hstmt, SQL_CLOSE);  
}  
Untuk informasi mengenai Lihat
Mengikat buffer ke kolom dalam tataan hasil Fungsi SQLBindCol
Membatalkan pemrosesan pernyataan Fungsi SQLCancel
Mengambil blok data atau menggulir melalui kumpulan hasil Fungsi SQLFetchScroll
Mendapatkan satu bidang dari deskriptor Fungsi SQLGetDescField
Mendapatkan beberapa bidang dari sebuah deskriptor Fungsi SQLGetDescRec
Mengatur satu bidang dari deskriptor Fungsi SQLSetDescField
Mengatur beberapa bidang dari sebuah deskriptor Fungsi SQLSetDescRec
Memposisikan kursor, menyegarkan data dalam rowset, atau memperbarui atau menghapus data dalam rowset Fungsi SQLSetPos
Mengatur atribut pernyataan Fungsi SQLSetStmtAttr