Untuk apa '$$' digunakan di PL / pgSQL

98

Benar-benar baru mengenal PL / pgSQL, apa arti tanda dolar ganda dalam fungsi ini :

CREATE OR REPLACE FUNCTION check_phone_number(text)
RETURNS boolean AS $$
BEGIN
  IF NOT $1 ~  e'^\\+\\d{3}\\ \\d{3} \\d{3} \\d{3}$' THEN
    RAISE EXCEPTION 'Wrong formated string "%". Expected format is +999 999';
  END IF;
  RETURN true; 
END;
$$ LANGUAGE plpgsql STRICT IMMUTABLE;

Saya menduga bahwa, dalam RETURNS boolean AS $$, $$adalah placeholder.

Baris terakhir adalah sedikit misteri: $$ LANGUAGE plpgsql STRICT IMMUTABLE;

Ngomong-ngomong, apa arti baris terakhir?

vektor
sumber
4
Mohon pertimbangkan untuk menandai jawaban Erwin sebagai jawaban atas pertanyaan ini, uraiannya menjelaskan apa yang sebenarnya $$dan Anda dapat mempelajari sesuatu yang baru dengan membacanya misalnya ada juga$foo$
csharpfolk

Jawaban:

143

Tanda dolar digunakan untuk mengutip dolar dan sama sekali tidak spesifik untuk definisi fungsi . Ini dapat digunakan untuk mengganti tanda kutip tunggal secara praktis di mana saja dalam skrip SQL.

Badan dari suatu fungsi merupakan literal string yang harus diapit oleh tanda kutip tunggal. Kutipan dolar adalah pengganti khusus PostgreSQL untuk tanda kutip tunggal untuk menghindari masalah kutipan di dalam badan fungsi. Anda juga bisa menulis definisi fungsi Anda dengan tanda kutip tunggal. Tapi kemudian Anda harus melepaskan semua tanda kutip tunggal di badan:

CREATE OR REPLACE FUNCTION check_phone_number(text)
RETURNS boolean AS
'
BEGIN
  IF NOT $1 ~  e''^\\+\\d{3}\\ \\d{3} \\d{3} \\d{3}$'' THEN
    RAISE EXCEPTION ''Malformed string "%". Expected format is +999 999'';
  END IF;
  RETURN true; 
END
' LANGUAGE plpgsql STRICT IMMUTABLE;

Ini bukan ide yang bagus. Gunakan kutipan dolar sebagai gantinya, lebih khusus juga letakkan token di antara $$untuk membuatnya unik - Anda mungkin ingin menggunakan $ -quotes di dalam badan fungsi juga. Sebenarnya aku sering melakukan itu.

CREATE OR REPLACE FUNCTION check_phone_number(text)
  RETURNS boolean  
AS
$func$
BEGIN
 ...
END
$func$  LANGUAGE plpgsql STRICT IMMUTABLE;

Rincian:

Seperti pertanyaan kedua Anda:
Baca paling baik manual padaCREATE FUNCTION memahami baris terakhir contoh Anda.

Erwin Brandstetter
sumber
1
Anda seharusnya mengatakan manual yang bagus , RTEM tidak memiliki cincin yang tepat untuk itu :)
mu terlalu pendek
@muistooshort: Saya buruk, mencoba variasi pada tema tampaknya telah merusak harmoni. Bagaimana Anda menyukai RTMEM? :)
Erwin Brandstetter
1
Saya mencoba meneriakkannya dan itu tidak sama. Meskipun demikian, ada beberapa situasi di mana kesopanan itu penting.
mu terlalu pendek
@ErwinBrandstetter Oke, tapi apa $body$? Dari CREATE OR REPLACE FUNCTION update_ts() RETURNS TRIGGER AS $BODY$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $BODY$ LANGUAGE plpgsql- Saya tidak melihat bodydefinisi di mana pun. Saya benar-benar tidak tahu apa yang terjadi di sini
Growler
2
@Growler: $body$hanya "mengutip dolar", seperti yang saya jelaskan. Detail lebih lanjut: stackoverflow.com/a/12320729/939860
Erwin Brandstetter
21

$$ adalah pembatas yang Anda gunakan untuk menunjukkan di mana definisi fungsi dimulai dan diakhiri. Simak berikut ini,

CREATE TABLE <name> <definition goes here> <options go here, eg: WITH OIDS>

Sintaks fungsi create serupa, tetapi karena Anda akan menggunakan semua jenis SQL dalam fungsi Anda (terutama akhir pernyataan; karakter), parser akan tersandung jika Anda tidak membatasinya. Jadi Anda harus membaca pernyataan Anda sebagai:

CREATE OR REPLACE FUNCTION check_phone_number(text)
RETURNS boolean AS <code delimited by $$> LANGUAGE plpgsql STRICT IMMUTABLE;

Hal-hal setelah definisi sebenarnya adalah opsi untuk memberi database lebih banyak informasi tentang fungsi Anda, sehingga dapat mengoptimalkan penggunaannya.

Faktanya jika Anda melihat di bawah "4.1.2.2. Konstanta String Kutipan Dolar" di manual, Anda akan melihat bahwa Anda bahkan dapat menggunakan karakter di antara simbol dolar dan semuanya akan dihitung sebagai satu pemisah.

Kapten Coder
sumber