Penting untuk memahami sifat utama dari kelima jenis data / simbol yang berbeda ini :
1. 'my_tbl'
Sebuah literal string dari unknown
ketik . Ketika digunakan dalam SQL (tertanam dalam kode plpgsql atau tidak), itu dipaksa ke jenis yang berasal dari konteks . Jika jenisnya tidak dapat ditentukan, pemeran eksplisit mungkin diperlukan. Seperti:'my_tbl'::text
.
2. 'my_tbl'::text
String literal yang sama dilemparkan ke ketik text
. Itu bisa menampung nama tabel, tapi sebenarnya hanya teks.
3. 'my_tbl'::regclass
pengidentifikasi objek (OID)
untuk kelas registered yang terdaftar . Ini ditampilkan dan dapat dimasukkan sebagai string yang mewakili nama objek yang valid ('my_tbl'
). Output secara otomatis memenuhi syarat skema ('my_schema.my_tbl'
) dan / atau tanda kutip ganda ('"mY_TbL"'
) jika itu akan menjadi ambigu atau ilegal. Ini bisa berupa tabel regular biasa , urutan , lihat , tampilan yang terwujud , jenis komposit dll. Detail dalam jawaban terkait ini:
4. my_tbl_var my_tbl
(kependekan dari my_tbl_var my_tbl%ROWTYPE
)
Dalam DECLARE
bagian dari blok kode plpgsql yang merupakan deklarasi variabel dengan terkenal jenis baris
(alias tipe komposit). Jenis harus didaftarkan di tabel sistem pg_class
(sama seperti dengan regclass
variabel). Ini bukan OID dari objek yang direferensikan, tetapi tipe barisnya yang sebenarnya. my_tbl_var
dan my_tbl
keduanya pengidentifikasi di sini dan tidak dapat diparameterisasi. Anda juga dapat mentransmisikan baris atau rekaman apa pun secara langsung:(123, 'foo')::my_tbl
5. my_tbl_var record
Dalam DECLARE
bagian dari blok kode plpgsql yang merupakan deklarasi anonim rekaman
. Pada dasarnya, placeholder untuk tipe baris yang belum diketahui / dengan struktur yang belum ditentukan. Ini dapat digunakan di sebagian besar tempat jenis baris dapat digunakan. Tetapi Anda tidak dapat mengakses bidang darinya sebelum variabel record ditetapkan.
Anda membingungkan 1. , 3. dan 4. dan selesaikan dengan menggunakan 5. sebagai gantinya.
Tapi ada lebih banyak kesalahan di sini:
-
Anda memilih seluruh tabel, tetapi variabel baris (catatan) hanya dapat menampung satu baris dalam satu waktu. Jadi hanya yang pertama ditugaskan dan dikembalikan. Meskipun tidak ada
ORDER BY
klausa, hasilnya arbitrer dan dapat berubah sewaktu-waktu. Perangkap jahat. -
Karena Anda sekarang menggunakan
record
ketik, Anda perlu memastikan itu telah ditetapkan sebelum Anda dapat menjalankan tes di bidangnya, atau Anda akan mendapatkan pengecualian untuk tabel kosong. Dalam kasus Anda, centangrecord_var IS NULL
hampir melakukan pekerjaan yang sama. Tetapi ada kasus sudut untuk baris dengan NULL di semua bidang:lalurecord_var IS NULL
mengevaluasi menjadi benar. Bahkan lebih sulit untuk pengujianIS NOT NULL
. Detailnya di sini:Saya menambahkan demo ke SQL fiddle di bawah.
-
Fungsi mengembalikan skalar tunggal (
boolean
) nilai. Gunakan:RETURN false;
Alih-alih:
RETURN QUERY SELECT false;
Fungsi
CREATE FUNCTION check_valid(_tbl regclass)
RETURNS bool AS
$func$
DECLARE
r record;
_row_ct int;
BEGIN
EXECUTE '
SELECT is_valid, hit_count, hit_limit
FROM ' || _tbl || '
ORDER <whatever>
LIMIT 1' -- replace <whatever> with your sort criteria
INTO r; -- only needed columns
GET DIAGNOSTICS _row_ct = ROW_COUNT;
IF _row_ct = 0 THEN -- necessary, because r may not be assigned
RETURN false;
ELSIF NOT r.is_valid OR r.hit_count > r.hit_limit THEN
RETURN false;
END IF;
RETURN true;
END
$func$ LANGUAGE plpgsql;
SQL Fiddle (dengan dua varian fungsi dan demo untuk baris IS NULL).
Poin utama
-
Gunakan
GET DIAGNOSTICS
untuk mengetahui apakah ada baris yang ditemukan dalam pernyataan dinamis denganEXECUTE
. -
IF
ekspresi dapat disederhanakan. -
Parameternya bertipe
regclass
, bukan hanya nama tabel. Saya tidak akan menggunakan nama "tablename" yang menyesatkan untuk parameter ini. Itu hanya menambah kebingungan awal Anda. Menyebutnya_tbl
sebagai gantinya.
Jika Anda ingin juga kembali satu set tipe baris variabel: