42.11. PL/pgSQL изнÑÑÑи #
Ð ÑÑом Ñазделе обÑÑждаÑÑÑÑ Ð½ÐµÐºÐ¾ÑоÑÑе деÑали ÑеализаÑии, коÑоÑÑе полÑзоваÑелÑм PL/pgSQL важно знаÑÑ.
42.11.1. ÐодÑÑановка пеÑеменнÑÑ #
SQL-опеÑаÑоÑÑ Ð¸ вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð²Ð½ÑÑÑи ÑÑнкÑии на PL/pgSQL могÑÑ ÑÑÑлаÑÑÑÑ Ð½Ð° пеÑеменнÑе и паÑамеÑÑÑ ÑÑой ÑÑнкÑии. Ðа кÑлиÑами PL/pgSQL заменÑÐµÑ Ð¿Ð°ÑамеÑÑÑ Ð·Ð°Ð¿ÑоÑов Ð´Ð»Ñ ÑÐ°ÐºÐ¸Ñ ÑÑÑлок. ÐаÑамеÑÑÑ Ð±ÑдÑÑ Ð·Ð°Ð¼ÐµÐ½ÐµÐ½Ñ ÑолÑко в меÑÑÐ°Ñ , где они ÑинÑакÑиÑеÑки допÑÑÑимÑ. Ðак кÑайний ÑлÑÑай, ÑаÑÑмоÑÑим ÑледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð¿Ð»Ð¾Ñ Ð¾Ð³Ð¾ ÑÑÐ¸Ð»Ñ Ð¿ÑогÑаммиÑованиÑ:
INSERT INTO foo (foo) VALUES (foo(foo));
ÐеÑвÑй Ñаз foo поÑвлÑеÑÑÑ Ð½Ð° Ñом меÑÑе, где ÑинÑакÑиÑеÑки должно бÑÑÑ Ð¸Ð¼Ñ ÑаблиÑÑ, поÑÑÐ¾Ð¼Ñ Ð·Ð°Ð¼ÐµÐ½Ñ Ð½Ðµ бÑдеÑ, даже еÑли ÑÑнкÑÐ¸Ñ Ð¸Ð¼ÐµÐµÑ Ð¿ÐµÑеменнÑÑ foo. ÐÑоÑой Ñаз foo вÑÑÑеÑаеÑÑÑ Ñам, где должно бÑÑÑ Ð¸Ð¼Ñ ÑÑолбÑа ÑаблиÑÑ, поÑÑÐ¾Ð¼Ñ Ð·Ð°Ð¼ÐµÐ½Ñ Ð½Ðµ бÑÐ´ÐµÑ Ð¸ здеÑÑ. ТÑеÑий Ñаз â на меÑÑе, где должно бÑÑÑ Ð¸Ð¼Ñ ÑÑнкÑии, поÑÑÐ¾Ð¼Ñ Ð·Ð°Ð¼ÐµÐ½Ñ Ð½Ðµ бÑдеÑ. ТолÑко поÑледнее вÑ
ождение foo ÑвлÑеÑÑÑ ÐºÐ°Ð½Ð´Ð¸Ð´Ð°Ñом на Ñо, ÑÑÐ¾Ð±Ñ Ð±ÑÑÑ ÑÑÑлкой на пеÑеменнÑÑ ÑÑнкÑии PL/pgSQL.
ÐбÑÑÑниÑÑ Ð¿ÑинÑип дейÑÑÐ²Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ еÑÑ Ð¸ Ñак: пÑи подÑÑановке пеÑеменнÑÑ Ð² SQL-ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð¼Ð¾Ð³ÑÑ Ð²ÑÑавлÑÑÑÑÑ ÑолÑко знаÑÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ ; пÑи ÑÑом нелÑÐ·Ñ Ð´Ð¸Ð½Ð°Ð¼Ð¸ÑеÑки менÑÑÑ Ð¾Ð±ÑекÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ , на коÑоÑÑе ÑÑÑлаеÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°. (ÐÐ»Ñ ÑÑого нÑжно ÑконÑÑÑÑиÑоваÑÑ ÑÑÑÐ¾ÐºÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð´Ð¸Ð½Ð°Ð¼Ð¸ÑеÑки, как опиÑано в ÐодÑазделе 42.5.4.)
ÐÑли имена пеÑеменнÑÑ ÑинÑакÑиÑеÑки не оÑлиÑаÑÑÑÑ Ð¾Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ð¹ ÑÑолбÑов ÑаблиÑÑ, Ñо возможна двÑÑмÑÑленноÑÑÑ Ð¸ в ÑÑÑÐ»ÐºÐ°Ñ Ð½Ð° ÑаблиÑÑ. ЯвлÑеÑÑÑ Ð»Ð¸ данное Ð¸Ð¼Ñ ÑÑÑлкой на ÑÑÐ¾Ð»Ð±ÐµÑ ÑаблиÑÑ Ð¸Ð»Ð¸ ÑÑÑлкой на пеÑеменнÑÑ? Ðзменим пÑедÑдÑÑий пÑимеÑ:
INSERT INTO dest (col) SELECT foo + bar FROM src;
ÐдеÑÑ dest и src Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð¸Ð¼ÐµÐ½Ð°Ð¼Ð¸ ÑаблиÑ, col должен бÑÑÑ ÑÑолбÑом dest. Ðднако foo и bar могÑÑ Ð±ÑÑÑ ÐºÐ°Ðº пеÑеменнÑми ÑÑнкÑии, Ñак и ÑÑолбÑами src.
Ðо ÑмолÑаниÑ, PL/pgSQL вÑдаÑÑ Ð¾ÑибкÑ, еÑли Ð¸Ð¼Ñ Ð² опеÑаÑоÑе SQL Ð¼Ð¾Ð¶ÐµÑ Ð¾ÑноÑиÑÑÑÑ ÐºÐ°Ðº к пеÑеменной, Ñак и к ÑÑолбÑÑ ÑаблиÑÑ. СиÑÑаÑÐ¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ иÑпÑавиÑÑ Ð¿ÐµÑеименованием пеÑеменной, пеÑеименованием ÑÑолбÑа, ÑоÑной квалиÑикаÑией неоднознаÑной ÑÑÑлки или Ñказанием PL/pgSQL маÑине, какÑÑ Ð¸Ð½ÑеÑпÑеÑаÑÐ¸Ñ Ð¿ÑедпоÑеÑÑÑ.
Самое пÑоÑÑое ÑеÑение â пеÑеименоваÑÑ Ð¿ÐµÑеменнÑÑ Ð¸Ð»Ð¸ ÑÑолбеÑ. ÐбÑее пÑавило кодиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¿ÑÐµÐ´Ð¿Ð¾Ð»Ð°Ð³Ð°ÐµÑ Ð¸ÑполÑзование ÑазлиÑнÑÑ
ÑоглаÑений о наименовании Ð´Ð»Ñ Ð¿ÐµÑеменнÑÑ
PL/pgSQL и ÑÑолбÑов ÑаблиÑ. ÐапÑимеÑ, еÑли имена пеÑеменнÑÑ
вÑегда имеÑÑ Ð²Ð¸Ð´ v_, а имена ÑÑолбÑов никогда не наÑинаÑÑÑÑ Ð½Ð° имÑv_, Ñо конÑликÑÑ Ð¸ÑклÑÑенÑ.
РкаÑеÑÑве алÑÑеÑнаÑÐ¸Ð²Ñ Ð¼Ð¾Ð¶Ð½Ð¾ дополниÑÑ Ð¸Ð¼ÐµÐ½Ð° неоднознаÑнÑÑ
ÑÑÑлок, ÑÑÐ¾Ð±Ñ ÑделаÑÑ Ð¸Ñ
ÑоÑнÑми. РпÑиведÑнном вÑÑе пÑимеÑе src.foo однознаÑно Ð±Ñ Ð¾Ð¿ÑеделÑлаÑÑ, как ÑÑÑлка на ÑÑÐ¾Ð»Ð±ÐµÑ ÑаблиÑÑ. ЧÑÐ¾Ð±Ñ ÑделаÑÑ Ð¾Ð´Ð½Ð¾Ð·Ð½Ð°Ñной ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑеменнÑÑ, пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° бÑÑÑ Ð¾Ð±ÑÑвлена в блоке Ñ Ð¼ÐµÑкой, и далее нÑжно иÑполÑзоваÑÑ ÑÑÑ Ð¼ÐµÑÐºÑ (Ñм. Раздел 42.2). ÐапÑимеÑ:
<<block>>
DECLARE
foo int;
BEGIN
foo := ...;
INSERT INTO dest (col) SELECT block.foo + bar FROM src; ÐдеÑÑ block.foo ÑÑÑлаеÑÑÑ Ð½Ð° пеÑеменнÑÑ, даже еÑли в ÑаблиÑе src еÑÑÑ ÑÑÐ¾Ð»Ð±ÐµÑ foo. ÐаÑамеÑÑÑ ÑÑнкÑии, а Ñакже ÑпеÑиалÑнÑе пеÑеменнÑе, Ñакие как FOUND, могÑÑ Ð±ÑÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ ÑÑнкÑии, поÑÐ¾Ð¼Ñ ÑÑо они неÑвно обÑÑÐ²Ð»ÐµÐ½Ñ Ð²Ð¾ внеÑнем блоке, меÑка коÑоÑого ÑÐ¾Ð²Ð¿Ð°Ð´Ð°ÐµÑ Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ ÑÑнкÑии.
Ðногда Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð½Ðµ оÑÐµÐ½Ñ Ð¿ÑакÑиÑнÑм иÑпÑавлÑÑÑ Ñаким ÑпоÑобом вÑе неоднознаÑнÑе ÑÑÑлки в болÑÑом кÑÑке PL/pgSQL кода. Ð ÑÐ°ÐºÐ¸Ñ ÑлÑÑаÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ ÑказаÑÑ, ÑÑÐ¾Ð±Ñ PL/pgSQL ÑазÑеÑал неоднознаÑнÑе ÑÑÑлки в полÑÐ·Ñ Ð¿ÐµÑеменнÑÑ (ÑÑо ÑовмеÑÑимо Ñ PL/pgSQL до веÑÑии PostgreSQL 9.0), или в полÑÐ·Ñ ÑÑолбÑов ÑаблиÑÑ (ÑовмеÑÑимо Ñ Ð½ÐµÐºÐ¾ÑоÑÑми дÑÑгими ÑиÑÑемами, Ñакими как Oracle).
Ðа ÑÑовне вÑей ÑиÑÑÐµÐ¼Ñ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ PL/pgSQL ÑегÑлиÑÑеÑÑÑ ÑÑÑановкой конÑигÑÑаÑионного паÑамеÑÑа plpgsql.variable_conflict, имеÑÑего знаÑениÑ: error, use_variable или use_column (error ÑÑÑанавливаеÑÑÑ Ð¿Ð¾ ÑмолÑÐ°Ð½Ð¸Ñ Ð¿Ñи ÑÑÑановке ÑиÑÑемÑ). Ðзменение ÑÑого паÑамеÑÑа влиÑÐµÑ Ð½Ð° вÑе поÑледÑÑÑие компилÑÑии опеÑаÑоÑов в ÑÑнкÑиÑÑ
на PL/pgSQL, но не на опеÑаÑоÑÑ Ñже ÑкомпилиÑованнÑе в ÑекÑÑем ÑеанÑе. Так как изменение ÑÑого паÑамеÑÑа Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑивеÑÑи к неожиданнÑм изменениÑм в поведении ÑÑнкÑий на PL/pgSQL, он Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸Ð·Ð¼ÐµÐ½Ñн ÑолÑко ÑÑпеÑполÑзоваÑелем.
Ðоведение PL/pgSQL можно изменÑÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ оÑделÑной ÑÑнкÑии, еÑли добавиÑÑ Ð² наÑало ÑÑнкÑии Ð¾Ð´Ð½Ñ Ð¸Ð· ÑÑÐ¸Ñ ÑпеÑиалÑнÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´:
#variable_conflict error #variable_conflict use_variable #variable_conflict use_column
ÐÑи ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð²Ð»Ð¸ÑÑÑ ÑолÑко на ÑÑнкÑиÑ, в коÑоÑой они запиÑÐ°Ð½Ñ Ð¸ пеÑекÑÑваÑÑ Ð´ÐµÐ¹ÑÑвие plpgsql.variable_conflict. ÐÑимеÑ:
CREATE FUNCTION stamp_user(id int, comment text) RETURNS void AS $$
#variable_conflict use_variable
DECLARE
curtime timestamp := now();
BEGIN
UPDATE users SET last_modified = curtime, comment = comment
WHERE users.id = id;
END;
$$ LANGUAGE plpgsql; Ркоманде UPDATE, curtime, comment и id бÑдÑÑ ÑÑÑлаÑÑÑÑ Ð½Ð° пеÑеменнÑе и паÑамеÑÑÑ ÑÑнкÑии вне завиÑимоÑÑи Ð¾Ñ Ñого, еÑÑÑ Ð»Ð¸ ÑÑолбÑÑ Ñ Ñакими именами в ÑаблиÑе users. ÐбÑаÑиÑе внимание, ÑÑо нÑжно дополниÑÑ Ð¸Ð¼ÐµÐ½ÐµÐ¼ ÑаблиÑÑ ÑÑÑÐ»ÐºÑ Ð½Ð° users.id в пÑедложении WHERE, ÑÑÐ¾Ð±Ñ Ð¾Ð½Ð° ÑÑÑлалаÑÑ Ð½Ð° ÑÑÐ¾Ð»Ð±ÐµÑ ÑаблиÑÑ. ÐÑи ÑÑом необÑзаÑелÑно дополнÑÑÑ ÑÑÑÐ»ÐºÑ Ð½Ð° comment в левой ÑаÑÑи ÑпиÑка UPDATE, Ñак как ÑинÑакÑиÑеÑки в ÑÑом меÑÑе должно бÑÑÑ Ð¸Ð¼Ñ ÑÑолбÑа ÑаблиÑÑ users. ÐÑÑ ÑÑнкÑÐ¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ бÑло Ð±Ñ Ð·Ð°Ð¿Ð¸ÑаÑÑ Ð¸ без завиÑимоÑÑи Ð¾Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ variable_conflict:
CREATE FUNCTION stamp_user(id int, comment text) RETURNS void AS $$
<<fn>>
DECLARE
curtime timestamp := now();
BEGIN
UPDATE users SET last_modified = fn.curtime, comment = stamp_user.comment
WHERE users.id = stamp_user.id;
END;
$$ LANGUAGE plpgsql;Ðамена пеÑеменнÑÑ
не пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð² ÑÑÑоке, иÑполнÑемой командой EXECUTE или ÐµÑ Ð²Ð°ÑианÑом. ÐÑли нÑжно вÑÑавлÑÑÑ Ð¸Ð·Ð¼ÐµÐ½ÑÑÑиеÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð² ÑакÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ, Ñо ÑÑо делаеÑÑÑ Ð»Ð¸Ð±Ð¾ пÑи поÑÑÑоении Ñамой командной ÑÑÑоки или Ñ Ð¸ÑполÑзованием USING, как показано в ÐодÑазделе 42.5.4.
Ðамена пеÑеменнÑÑ
в наÑÑоÑÑее вÑÐµÐ¼Ñ ÑабоÑÐ°ÐµÑ ÑолÑко в командаÑ
SELECT, INSERT, UPDATE, DELETE и командаÑ
, ÑодеÑжаÑиÑ
Ð¾Ð´Ð½Ñ Ð¸Ð· вÑÑепеÑеÑиÑленнÑÑ
(напÑимеÑ, EXPLAIN и CREATE TABLE ... AS SELECT), поÑÐ¾Ð¼Ñ ÑÑо оÑновной иÑполниÑÐµÐ»Ñ SQL допÑÑÐºÐ°ÐµÑ Ð¸ÑполÑзование паÑамеÑÑов запÑоÑа ÑолÑко в ÑÑиÑ
командаÑ
. ЧÑÐ¾Ð±Ñ Ð¸ÑполÑзоваÑÑ Ð¸Ð·Ð¼ÐµÐ½ÑемÑе имена или знаÑÐµÐ½Ð¸Ñ Ð² дÑÑгиÑ
ÑипаÑ
опеÑаÑоÑов (обÑÑно назÑваемÑе ÑлÑжебнÑми), необÑ
одимо ÑоÑÑавиÑÑ ÑекÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð² виде ÑÑÑоки и вÑполниÑÑ ÐµÑ Ð² EXECUTE.
42.11.2. ÐеÑиÑование плана #
ÐнÑеÑпÑеÑаÑÐ¾Ñ PL/pgSQL анализиÑÑÐµÑ Ð¸ÑÑ Ð¾Ð´Ð½Ñй ÑекÑÑ ÑÑнкÑии и ÑÑÑÐ¾Ð¸Ñ Ð²Ð½ÑÑÑеннее бинаÑное деÑево инÑÑÑÑкÑий пÑи пеÑвом вÑзове ÑÑнкÑии (Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑеанÑа). РдеÑево инÑÑÑÑкÑий полноÑÑÑÑ Ð¿ÐµÑеводиÑÑÑ Ð²ÑÑ ÑÑÑÑкÑÑÑа опеÑаÑоÑов PL/pgSQL, но Ð´Ð»Ñ Ð²ÑÑажений и команд SQL, иÑполÑзÑемÑÑ Ð² ÑÑнкÑии, ÑÑо пÑоиÑÑ Ð¾Ð´Ð¸Ñ Ð½Ðµ ÑÑазÑ.
ÐÑи пеÑвом вÑполнении в ÑÑнкÑии каждого вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL инÑеÑпÑеÑаÑÐ¾Ñ PL/pgSQL ÑазбиÑÐ°ÐµÑ Ð¸ анализиÑÑÐµÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð´Ð³Ð¾Ñовленного к вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑаÑоÑа Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑÑнкÑии SPI_prepare менеджеÑа инÑеÑÑейÑа пÑогÑаммиÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑеÑвеÑа. ÐоÑледÑÑÑие обÑаÑÐµÐ½Ð¸Ñ Ðº ÑÑÐ¾Ð¼Ñ Ð²ÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ команде повÑоÑно иÑполÑзÑÑÑ Ð¿Ð¾Ð´Ð³Ð¾ÑовленнÑй к вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑаÑоÑ. Таким обÑазом, SQL-командÑ, наÑ
одÑÑиеÑÑ Ð² Ñедко поÑеÑаемой веÑке кода ÑÑловного опеÑаÑоÑа, не неÑÑÑ Ð½Ð°ÐºÐ»Ð°Ð´Ð½ÑÑ
ÑаÑÑ
одов на ÑÐ°Ð·Ð±Ð¾Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´, еÑли они Ñак и не бÑдÑÑ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ñ Ð² ÑекÑÑем ÑеанÑе. ÐдеÑÑ ÐµÑÑÑ Ð½ÐµÐ´Ð¾ÑÑаÑок, заклÑÑаÑÑийÑÑ Ð² Ñом, ÑÑо оÑибки в опÑеделÑнном вÑÑажении или команде не могÑÑ Ð±ÑÑÑ Ð¾Ð±Ð½Ð°ÑÑженÑ, пока вÑполнение не дойдÑÑ Ð´Ð¾ ÑÑой ÑаÑÑи ÑÑнкÑии. (ТÑивиалÑнÑе ÑинÑакÑиÑеÑкие оÑибки обнаÑÑжаÑÑÑ Ð² Ñ
оде пеÑвонаÑалÑного ÑазбоÑа, но ниÑего более ÑеÑÑÑзного не бÑÐ´ÐµÑ Ð¾Ð±Ð½Ð°ÑÑжено до иÑполнениÑ.)
ÐÑоме Ñого, PL/pgSQL (ÑоÑнее, Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ Ð¸Ð½ÑеÑÑейÑа пÑогÑаммиÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑеÑвеÑа) бÑÐ´ÐµÑ Ð¿ÑÑаÑÑÑÑ ÐºÐµÑиÑоваÑÑ Ð¿Ð»Ð°Ð½ вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð»Ñбого подгоÑовленного к иÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑаÑоÑа. ÐÑи каждом вÑзове опеÑаÑоÑа, еÑли не иÑполÑзÑеÑÑÑ Ð¿Ð»Ð°Ð½ из кеÑа, генеÑиÑÑеÑÑÑ Ð½Ð¾Ð²Ñй план вÑполнениÑ, и ÑекÑÑие знаÑÐµÐ½Ð¸Ñ Ð¿Ð°ÑамеÑÑов (Ñо еÑÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¿ÐµÑеменнÑÑ PL/pgSQL) могÑÑ Ð±ÑÑÑ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ñ Ð´Ð»Ñ Ð¾Ð¿ÑимизаÑии нового плана. ÐÑли опеÑаÑÐ¾Ñ Ð½Ðµ Ð¸Ð¼ÐµÐµÑ Ð¿Ð°ÑамеÑÑов или вÑполнÑеÑÑÑ Ð¼Ð½Ð¾Ð³Ð¾ Ñаз, Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ Ð¸Ð½ÑеÑÑейÑа пÑогÑаммиÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑеÑвеÑа ÑаÑÑмоÑÑÐ¸Ñ Ð²Ð¾Ð¿ÑÐ¾Ñ Ð¾ Ñоздании и кеÑиÑовании (Ð´Ð»Ñ Ð¿Ð¾Ð²ÑоÑного иÑполÑзованиÑ) обÑего плана, не завиÑÑÑего Ð¾Ñ Ð·Ð½Ð°Ñений паÑамеÑÑов. Ðак пÑавило, ÑÑо пÑоиÑÑ Ð¾Ð´Ð¸Ñ Ð² ÑÐµÑ ÑлÑÑаÑÑ , когда план вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð½Ðµ оÑÐµÐ½Ñ ÑÑвÑÑвиÑелен к имеÑÑимÑÑ ÑÑÑлкам на знаÑÐµÐ½Ð¸Ñ Ð¿ÐµÑеменнÑÑ PL/pgSQL. РпÑоÑивном ÑлÑÑае вÑгоднее каждÑй Ñаз ÑоÑмиÑоваÑÑ Ð½Ð¾Ð²Ñй план. Ðолее подÑобно поведение подгоÑовленнÑÑ Ð¾Ð¿ÐµÑаÑоÑов ÑаÑÑмаÑÑиваеÑÑÑ Ð² PREPARE.
ЧÑÐ¾Ð±Ñ PL/pgSQL мог ÑоÑ
ÑанÑÑÑ Ð¿Ð¾Ð´Ð³Ð¾ÑовленнÑе опеÑаÑоÑÑ Ð¸ Ð¿Ð»Ð°Ð½Ñ Ð²ÑполнениÑ, ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SQL в коде PL/pgSQL, Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¸ÑполÑзоваÑÑ Ð¾Ð´Ð½Ð¸ и Ñе же ÑаблиÑÑ Ð¸ ÑÑолбÑÑ Ð¿Ñи каждом иÑполнении. Ð ÑÑо знаÑиÑ, ÑÑо в SQL-командаÑ
нелÑÐ·Ñ Ð¸ÑполÑзоваÑÑ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ñ ÑÐ°Ð±Ð»Ð¸Ñ Ð¸ ÑÑолбÑов в каÑеÑÑве паÑамеÑÑов. ЧÑÐ¾Ð±Ñ Ð¾Ð±Ð¾Ð¹Ñи ÑÑо огÑаниÑение, нÑжно ÑконÑÑÑÑиÑоваÑÑ Ð´Ð¸Ð½Ð°Ð¼Ð¸ÑеÑкÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð´Ð»Ñ Ð¾Ð¿ÐµÑаÑоÑа PL/pgSQL EXECUTE â Ñеной бÑÐ´ÐµÑ ÑÐ°Ð·Ð±Ð¾Ñ Ð¸ поÑÑÑоение нового плана вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ñи каждом вÑзове.
ÐзменÑÐ¸Ð²Ð°Ñ Ð¿ÑиÑода пеÑеменнÑÑ
Ñипа record пÑедÑÑавлÑÐµÑ ÐµÑÑ Ð¾Ð´Ð½Ñ Ð¿ÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð² ÑÑой ÑвÑзи. Ðогда Ð¿Ð¾Ð»Ñ Ð¿ÐµÑеменной Ñипа record иÑполÑзÑÑÑÑÑ Ð² вÑÑажениÑÑ
или опеÑаÑоÑаÑ
, ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ
полей не Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¼ÐµÐ½ÑÑÑÑÑ Ð¾Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ вÑзова ÑÑнкÑии к дÑÑгомÑ, Ñак как пÑи анализе каждого вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð±ÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ ÑÐ¾Ñ Ñип даннÑÑ
, коÑоÑÑй пÑиÑÑÑÑÑвовал пÑи пеÑвом вÑзове. ÐÑи необÑ
одимоÑÑи можно иÑполÑзоваÑÑ EXECUTE Ð´Ð»Ñ ÑеÑÐµÐ½Ð¸Ñ ÑÑой пÑоблемÑ.
ÐÑли ÑÑнкÑÐ¸Ñ Ð¸ÑполÑзÑеÑÑÑ Ð² каÑеÑÑве ÑÑиггеÑа более Ñем Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð¹ ÑаблиÑÑ, PL/pgSQL незавиÑимо подгоÑÐ°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð¸ кеÑиÑÑÐµÑ Ð¾Ð¿ÐµÑаÑоÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ Ñакой ÑаблиÑÑ. То еÑÑÑ ÑоздаÑÑÑÑ ÐºÐµÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ комбинаÑии ÑÑиггеÑÐ½Ð°Ñ ÑÑнкÑÐ¸Ñ + ÑаблиÑа, а не ÑолÑко Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑнкÑии. ÐÑо ÑÑÑÑанÑÐµÑ Ð½ÐµÐºÐ¾ÑоÑÑе пÑоблемÑ, ÑвÑзаннÑе Ñ ÑазлиÑнÑми Ñипами даннÑÑ
. ÐапÑимеÑ, ÑÑиггеÑÐ½Ð°Ñ ÑÑнкÑÐ¸Ñ ÑÐ¼Ð¾Ð¶ÐµÑ ÑÑпеÑно ÑабоÑаÑÑ Ñо ÑÑолбÑом key, даже еÑли в ÑазнÑÑ
ÑаблиÑаÑ
ÑÑÐ¾Ñ ÑÑÐ¾Ð»Ð±ÐµÑ Ð¸Ð¼ÐµÐµÑ ÑазнÑе ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ
.
Таким же обÑазом, ÑÑнкÑии Ñ Ð¿Ð¾Ð»Ð¸Ð¼Ð¾ÑÑнÑми Ñипами аÑгÑменÑов имеÑÑ Ð¾ÑделÑнÑй ÐºÐµÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ комбинаÑии ÑакÑиÑеÑÐºÐ¸Ñ Ñипов аÑгÑменÑов, Ñак ÑÑо ÑазлиÑÐ¸Ñ Ñипов даннÑÑ Ð½Ðµ вÑзÑваÑÑ Ð½ÐµÐ¾Ð¶Ð¸Ð´Ð°Ð½Ð½ÑÑ Ñбоев.
ÐеÑиÑование опеÑаÑоÑов иногда пÑÐ¸Ð²Ð¾Ð´Ð¸Ñ Ðº неожиданнÑм ÑÑÑекÑам пÑи инÑеÑпÑеÑаÑии ÑÑвÑÑвиÑелÑнÑÑ ÐºÐ¾ вÑемени знаÑений. ÐапÑимеÑ, еÑÑÑ ÑазниÑа Ð¼ÐµÐ¶Ð´Ñ Ñем, ÑÑо делаÑÑ ÑÑи две ÑÑнкÑии:
CREATE FUNCTION logfunc1(logtxt text) RETURNS void AS $$
BEGIN
INSERT INTO logtable VALUES (logtxt, 'now');
END;
$$ LANGUAGE plpgsql;и
CREATE FUNCTION logfunc2(logtxt text) RETURNS void AS $$
DECLARE
curtime timestamp;
BEGIN
curtime := 'now';
INSERT INTO logtable VALUES (logtxt, curtime);
END;
$$ LANGUAGE plpgsql;Ð ÑлÑÑае logfunc1, пÑи анализе INSERT, оÑновной анализаÑÐ¾Ñ Postgres Pro знаеÑ, ÑÑо ÑÑÑÐ¾ÐºÑ 'now' ÑледÑÐµÑ ÑолковаÑÑ ÐºÐ°Ðº timestamp, поÑÐ¾Ð¼Ñ ÑÑо Ñелевой ÑÑÐ¾Ð»Ð±ÐµÑ ÑаблиÑÑ logtable Ð¸Ð¼ÐµÐµÑ Ñакой Ñип даннÑÑ
. Таким обÑазом, 'now' бÑÐ´ÐµÑ Ð¿ÑеобÑазовано в конÑÑанÑÑ timestamp пÑи анализе INSERT, а заÑем ÑÑа конÑÑанÑа бÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ Ð² поÑледÑÑÑиÑ
вÑзоваÑ
logfunc1 в ÑеÑение вÑего ÑеанÑа. РазÑмееÑÑÑ, ÑÑо не Ñо, ÑÑо Ñ
оÑел пÑогÑаммиÑÑ. ÐÑÑÑе бÑло Ð±Ñ Ð¸ÑполÑзоваÑÑ ÑÑнкÑÐ¸Ñ now() или current_timestamp.
Ð ÑлÑÑае logfunc2, оÑновной анализаÑÐ¾Ñ Postgres Pro не знаеÑ, какого Ñипа бÑÐ´ÐµÑ 'now' и поÑÑÐ¾Ð¼Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ Ð·Ð½Ð°Ñение Ñипа text, ÑодеÑжаÑее ÑÑÑÐ¾ÐºÑ now. ÐÑи поÑледÑÑÑем пÑиÑваивании локалÑной пеÑеменной curtime инÑеÑпÑеÑаÑÐ¾Ñ PL/pgSQL пÑÐ¸Ð²Ð¾Ð´Ð¸Ñ ÑÑÑ ÑÑÑÐ¾ÐºÑ Ðº ÑÐ¸Ð¿Ñ timestamp, вÑзÑÐ²Ð°Ñ ÑÑнкÑии textout и timestamp_in. Таким обÑазом, меÑка вÑемени бÑÐ´ÐµÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÑÑÑÑÑ Ð¿Ñи каждом вÑполнении, как и ожидаеÑÑÑ Ð¿ÑогÑаммиÑÑом. Ð Ñ
оÑÑ Ð²ÑÑ ÑабоÑÐ°ÐµÑ ÐºÐ°Ðº ожидалоÑÑ, ÑÑо не ÑлиÑком ÑÑÑекÑивно, поÑÑÐ¾Ð¼Ñ Ð¸ÑполÑзование ÑÑнкÑии now() по-пÑÐµÐ¶Ð½ÐµÐ¼Ñ Ð·Ð½Ð°ÑиÑелÑно лÑÑÑе.