| ÐокÑменÑаÑÐ¸Ñ Ð¿Ð¾ PostgreSQL 9.4.1 | |||
|---|---|---|---|
| ÐÑед. | УÑÐ¾Ð²ÐµÐ½Ñ Ð²ÑÑе | Ðлава 43. PL/Python â пÑоÑедÑÑнÑй ÑзÑк Python | След. |
43.7. ÐбÑаÑение к базе даннÑÑ
ÐÑполниÑÐµÐ»Ñ ÑзÑка PL/Python авÑомаÑиÑеÑки импоÑÑиÑÑÐµÑ Ð¼Ð¾Ð´ÑÐ»Ñ Python Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ plpy. ÐÑ Ð² ÑвоÑм коде можеÑе иÑполÑзоваÑÑ ÑÑнкÑии и конÑÑанÑÑ, обÑÑвленнÑе в ÑÑом модÑле, обÑаÑаÑÑÑ Ðº ним по именам вида plpy.имÑ.
43.7.1. ФÑнкÑии обÑаÑÐµÐ½Ð¸Ñ Ðº базе даннÑÑ
ÐодÑÐ»Ñ plpy ÑодеÑÐ¶Ð¸Ñ ÑазлиÑнÑе ÑÑнкÑии Ð´Ð»Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´ в базе даннÑÑ :
- plpy.
execute(запÑÐ¾Ñ [, макÑ-ÑÑÑок]) ÐÑи вÑзове
plpy.executeÑо ÑÑÑокой запÑоÑа и необÑзаÑелÑнÑм аÑгÑменÑом, огÑаниÑиваÑÑим ÑиÑло ÑÑÑок, вÑполнÑеÑÑÑ Ð·Ð°Ð´Ð°Ð½Ð½Ñй запÑоÑ, а Ñо, ÑÑо он вÑдаÑÑ, возвÑаÑаеÑÑÑ Ð² виде обÑекÑа ÑезÑлÑÑаÑа.ÐбÑÐµÐºÑ ÑезÑлÑÑаÑа имиÑиÑÑÐµÑ ÑпиÑок или ÑловаÑÑ. ÐолÑÑиÑÑ Ð¸Ð· него даннÑе можно по номеÑÑ ÑÑÑоки и имени колонки. ÐапÑимеÑ, команда:
rv = plpy.execute("SELECT * FROM my_table", 5)веÑнÑÑ Ð½Ðµ более 5 ÑÑÑок из оÑноÑÐµÐ½Ð¸Ñ my_table. ÐÑли в my_table еÑÑÑ ÐºÐ¾Ð»Ð¾Ð½ÐºÐ° my_column, к ней можно обÑаÑиÑÑÑÑ Ñак:
foo = rv[i]["my_column"]
ЧиÑло возвÑаÑÑннÑÑ Ð² ÑÑом обÑекÑе ÑÑÑок можно полÑÑиÑÑ, воÑполÑзовавÑиÑÑ Ð²ÑÑÑоенной ÑÑнкÑией
len.ÐÐ»Ñ Ð¾Ð±ÑекÑа ÑезÑлÑÑаÑа опÑÐµÐ´ÐµÐ»ÐµÐ½Ñ ÑледÑÑÑие дополниÑелÑнÑе меÑодÑ:
nrows()ÐозвÑаÑÐ°ÐµÑ ÑиÑло ÑÑÑок, обÑабоÑаннÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¾Ð¹. ÐамеÑÑÑе, ÑÑо ÑÑо ÑиÑло не обÑзаÑелÑно бÑÐ´ÐµÑ Ñавно ÑиÑÐ»Ñ Ð²Ð¾Ð·Ð²ÑаÑÑннÑÑ ÑÑÑок. ÐапÑимеÑ, команда UPDATE ÑÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ ÑÑо знаÑение, но не возвÑаÑÐ°ÐµÑ ÑÑÑок (без ÑÐºÐ°Ð·Ð°Ð½Ð¸Ñ RETURNING).
status()ÐнаÑение ÑоÑÑоÑниÑ, возвÑаÑÑнное
SPI_execute().colnames()coltypes()coltypmods()ÐозвÑаÑаÑÑ ÑпиÑок имÑн колонок, ÑпиÑок OID Ñипов колонок и ÑпиÑок модиÑикаÑоÑов Ñипа ÑÑÐ¸Ñ ÐºÐ¾Ð»Ð¾Ð½Ð¾Ðº, ÑооÑвеÑÑÑвенно.
ÐÑи меÑÐ¾Ð´Ñ Ð²ÑзÑваÑÑ Ð¸ÑклÑÑение, когда им пеÑедаÑÑÑÑ Ð¾Ð±ÑекÑ, полÑÑеннÑй Ð¾Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ, не возвÑаÑаÑÑей ÑезÑлÑÑиÑÑÑÑий набоÑ, напÑимеÑ, UPDATE без RETURNING, либо DROP TABLE. Ðо ÑÑи меÑÐ¾Ð´Ñ Ð²Ð¿Ð¾Ð»Ð½Ðµ можно иÑполÑзоваÑÑ Ñ ÑезÑлÑÑаÑом, ÑодеÑжаÑим Ð½Ð¾Ð»Ñ ÑÑÑок.
__str__()СÑандаÑÑнÑй меÑод __str__ опÑеделÑн Ñак, ÑÑÐ¾Ð±Ñ Ð¼Ð¾Ð¶Ð½Ð¾ бÑло, напÑимеÑ, вÑвеÑÑи оÑладоÑное ÑообÑение Ñ ÑезÑлÑÑаÑами запÑоÑа, вÑзвав plpy.debug(rv).
ÐбÑÐµÐºÑ ÑезÑлÑÑаÑа Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸Ð·Ð¼ÐµÐ½Ñн.
ÐамеÑÑÑе, ÑÑо пÑи вÑзове plpy.execute веÑÑ Ð½Ð°Ð±Ð¾Ñ ÑезÑлÑÑаÑов бÑÐ´ÐµÑ Ð¿ÑоÑиÑан в памÑÑÑ. ÐÑÑ ÑÑнкÑÐ¸Ñ ÑледÑÐµÑ Ð¸ÑполÑзоваÑÑ, ÑолÑко еÑли Ð²Ñ Ð·Ð½Ð°ÐµÑе, ÑÑо Ð½Ð°Ð±Ð¾Ñ Ð±ÑÐ´ÐµÑ Ð¾ÑноÑиÑелÑно неболÑÑим. ÐÑли Ð²Ñ Ñ Ð¾ÑиÑе иÑклÑÑиÑÑ ÑиÑк пеÑÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ð°Ð¼ÑÑи пÑи вÑбоÑке ÑезÑлÑÑаÑов болÑÑого обÑÑма, иÑполÑзÑйÑе plpy.cursor вмеÑÑо plpy.execute.
- plpy.
prepare(запÑÐ¾Ñ [, ÑипÑ_аÑгÑменÑов])
plpy.execute(план [, аÑгÑменÑÑ [, макÑ-ÑÑÑок]]) ФÑнкÑиÑ
plpy.prepareподгоÑÐ°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð¿Ð»Ð°Ð½ вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð·Ð°Ð¿ÑоÑа. Ðна вÑзÑваеÑÑÑ Ñо ÑÑÑокой запÑоÑа и ÑпиÑком Ñипов паÑамеÑÑов (еÑли в запÑоÑе еÑÑÑ Ð¿Ð°ÑамеÑÑÑ). ÐапÑимеÑ:plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = $1", ["text"])ÐдеÑÑ text пÑедÑÑавлÑÐµÑ Ð¿ÐµÑеменнÑÑ, пеÑедаваемÑÑ Ð² каÑеÑÑве паÑамеÑÑа $1. ÐÑоÑой аÑгÑÐ¼ÐµÐ½Ñ Ð½ÐµÐ¾Ð±ÑзаÑелен, еÑли запÑоÑÑ Ð½Ðµ нÑжно пеÑедаваÑÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ðµ паÑамеÑÑÑ.
ЧÑÐ¾Ð±Ñ Ð·Ð°Ð¿ÑÑÑиÑÑ Ð¿Ð¾Ð´Ð³Ð¾ÑовленнÑй опеÑаÑÐ¾Ñ Ð½Ð° вÑполнение, иÑполÑзÑйÑе ваÑиаÑÐ¸Ñ ÑÑнкÑии
plpy.execute:rv = plpy.execute(plan, ["name"], 5)
ÐеÑедайÑе план в пеÑвом аÑгÑменÑе (вмеÑÑо ÑÑÑоки запÑоÑа), а ÑпиÑок знаÑений, коÑоÑÑе бÑдÑÑ Ð¿Ð¾Ð´ÑÑÐ°Ð²Ð»ÐµÐ½Ñ Ð² запÑоÑ, â во вÑоÑом. ÐÑоÑой аÑгÑÐ¼ÐµÐ½Ñ Ð¼Ð¾Ð¶Ð½Ð¾ опÑÑÑиÑÑ, еÑли запÑÐ¾Ñ Ð½Ðµ пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ðµ паÑамеÑÑÑ. ТÑеÑий аÑгÑменÑ, как и ÑанÑÑе, задаÑÑ Ð½ÐµÐ¾Ð±ÑзаÑелÑное огÑаниÑение макÑималÑного ÑиÑла ÑÑÑок.
ÐаÑамеÑÑÑ Ð·Ð°Ð¿ÑоÑа и Ð¿Ð¾Ð»Ñ Ð² обÑекÑе ÑезÑлÑÑаÑа пÑеобÑазÑÑÑÑÑ Ð¼ÐµÐ¶Ð´Ñ Ñипами даннÑÑ PostgreSQL и Python как опиÑано в Разделе 43.3. Ðо еÑÑÑ Ð¾Ð´Ð½Ð¾ иÑклÑÑение â ÑоÑÑавнÑе ÑÐ¸Ð¿Ñ Ð² наÑÑоÑÑее вÑÐµÐ¼Ñ Ð½Ðµ поддеÑживаÑÑÑÑ: они не бÑдÑÑ Ð¿ÑинÑÑÑ Ð² каÑеÑÑве паÑамеÑÑов запÑоÑа и бÑдÑÑ Ð¿ÑеобÑÐ°Ð·Ð¾Ð²Ð°Ð½Ñ Ð² ÑÑÑоки, еÑли окажÑÑÑÑ Ð² ÑезÑлÑÑаÑе запÑоÑа. РкаÑеÑÑве Ð¾Ð±Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ ÑеÑÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ пÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð¸Ð½Ð¾Ð³Ð´Ð° можно пеÑепиÑаÑÑ Ð·Ð°Ð¿ÑÐ¾Ñ Ñак, ÑÑÐ¾Ð±Ñ ÑезÑлÑÑÐ°Ñ ÑоÑÑавного Ñипа вÑдавалÑÑ ÐºÐ°Ðº коÑÑеж, а не как поле ÑезÑлÑÑиÑÑÑÑего коÑÑежа. РезÑлÑÑиÑÑÑÑÑÑ ÑÑÑÐ¾ÐºÑ Ñакже можно вÑÑÑнÑÑ ÑазобÑаÑÑ Ð¿Ð¾ ÑаÑÑÑм, но ÑÑÐ¾Ñ Ð¿Ð¾Ð´Ñ Ð¾Ð´ не ÑекомендÑеÑÑÑ, Ñак как он пÑовоÑиÑÑÐµÑ Ð¿ÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð² бÑдÑÑем.
Ðогда Ð²Ñ Ð¿Ð¾Ð´Ð³Ð¾ÑавливаеÑе план, иÑполÑзÑÑ Ð¼Ð¾Ð´ÑÐ»Ñ PL/Python, он ÑÐ¾Ñ ÑанÑеÑÑÑ Ð°Ð²ÑомаÑиÑеÑки. ЧÑо ÑÑо ознаÑаеÑ, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе ÑзнаÑÑ Ð² докÑменÑаÑии SPI (Ðлава 44). ЧÑÐ¾Ð±Ñ ÑÑÑекÑивно иÑполÑзоваÑÑ ÑÑо в неÑколÑÐºÐ¸Ñ Ð²ÑÐ·Ð¾Ð²Ð°Ñ ÑÑнкÑии, Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾ÑÑебоваÑÑÑÑ Ð¿ÑимениÑÑ ÑловаÑÑ Ð¿Ð¾ÑÑоÑнного Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ SD или GD (Ñм. Раздел 43.4). ÐапÑимеÑ:
CREATE FUNCTION usesavedplan() RETURNS trigger AS $$ if "plan" in SD: plan = SD["plan"] else: plan = plpy.prepare("SELECT 1") SD["plan"] = plan # оÑÑалÑной код ÑÑнкÑии $$ LANGUAGE plpythonu;- plpy.
cursor(запÑоÑ)
plpy.cursor(план [, аÑгÑменÑÑ]) ФÑнкÑÐ¸Ñ plpy.cursor пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ñе же аÑгÑменÑÑ, ÑÑо и plpy.execute (кÑоме огÑаниÑÐµÐ½Ð¸Ñ ÑÑÑок) и возвÑаÑÐ°ÐµÑ Ð¾Ð±ÑÐµÐºÑ ÐºÑÑÑоÑа, коÑоÑÑй позволÑÐµÑ Ð¾Ð±ÑабаÑÑваÑÑ Ð¾Ð±ÑÑмнÑе набоÑÑ ÑезÑлÑÑаÑов неболÑÑими поÑÑиÑми. Ðак и plpy.execute, ÑÑой ÑÑнкÑии можно пеÑедаÑÑ ÑÑÑÐ¾ÐºÑ Ð·Ð°Ð¿ÑоÑа или обÑекÑа плана, вмеÑÑе Ñо ÑпиÑком аÑгÑменÑов.
ÐбÑÐµÐºÑ ÐºÑÑÑоÑа ÑеализÑÐµÑ Ð¼ÐµÑод fetch, коÑоÑÑй пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ ÑелоÑиÑленнÑй паÑамеÑÑ Ð¸ возвÑаÑÐ°ÐµÑ Ð¾Ð±ÑÐµÐºÑ ÑезÑлÑÑаÑа. ÐÑи каждом ÑледÑÑÑем вÑзове fetch возвÑаÑаемÑй обÑÐµÐºÑ Ð±ÑÐ´ÐµÑ ÑодеÑжаÑÑ ÑледÑÑÑий Ð½Ð°Ð±Ð¾Ñ ÑÑÑок, в колиÑеÑÑве, не пÑевÑÑаÑÑем знаÑение паÑамеÑÑа. Ðогда ÑÑÑоки законÑаÑÑÑ, fetch наÑнÑÑ Ð²Ð¾Ð·Ð²ÑаÑаÑÑ Ð¿ÑÑÑой обÑÐµÐºÑ ÑезÑлÑÑаÑа. ÐбÑекÑÑ ÐºÑÑÑоÑа Ñакже пÑедоÑÑавлÑÑÑ Ð¸Ð½ÑеÑÑÐµÐ¹Ñ Ð¸ÑеÑаÑоÑа, вÑдаÑÑий по ÑÑÑоке за один Ñаз, пока не бÑдÑÑ Ð²ÑÐ´Ð°Ð½Ñ Ð²Ñе ÑÑÑоки. ÐаннÑе, вÑбиÑаемÑе Ñаким обÑазом, возвÑаÑаÑÑÑÑ Ð½Ðµ как обÑекÑÑ ÑезÑлÑÑаÑа, а как ÑловаÑи (одной ÑÑÑоке ÑезÑлÑÑаÑа ÑооÑвеÑÑÑвÑÐµÑ Ð¾Ð´Ð¸Ð½ ÑловаÑÑ).
СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑиÑÑÐµÑ Ð¾Ð±ÑабоÑÐºÑ ÑодеÑжимого болÑÑой ÑаблиÑÑ Ð´Ð²ÑÐ¼Ñ ÑпоÑобами:
CREATE FUNCTION count_odd_iterator() RETURNS integer AS $$ odd = 0 for row in plpy.cursor("select num from largetable"): if row['num'] % 2: odd += 1 return odd $$ LANGUAGE plpythonu; CREATE FUNCTION count_odd_fetch(batch_size integer) RETURNS integer AS $$ odd = 0 cursor = plpy.cursor("select num from largetable") while True: rows = cursor.fetch(batch_size) if not rows: break for row in rows: if row['num'] % 2: odd += 1 return odd $$ LANGUAGE plpythonu; CREATE FUNCTION count_odd_prepared() RETURNS integer AS $$ odd = 0 plan = plpy.prepare("select num from largetable where num % $1 <> 0", ["integer"]) rows = list(plpy.cursor(plan, [2])) return len(rows) $$ LANGUAGE plpythonu;ÐÑÑÑоÑÑ Ð»Ð¸ÐºÐ²Ð¸Ð´Ð¸ÑÑÑÑÑÑ Ð°Ð²ÑомаÑиÑеÑки. Ðо еÑли Ð²Ñ Ñ Ð¾ÑиÑе Ñвно оÑвободиÑÑ Ð²Ñе ÑеÑÑÑÑÑ, занÑÑÑе кÑÑÑоÑом, вÑзовиÑе меÑод close. ÐÑодолжаÑÑ Ð¿Ð¾Ð»ÑÑаÑÑ Ð´Ð°Ð½Ð½Ñе ÑеÑез кÑÑÑоÑ, коÑоÑÑй бÑл закÑÑÑ, нелÑзÑ.
ÐодÑказка: Ðе пÑÑайÑе обÑекÑÑ, ÑоздаваемÑе ÑÑнкÑией plpy.cursor, Ñ ÐºÑÑÑоÑами DB-API, опÑеделÑннÑми в ÑпеÑиÑикаÑии API Ð´Ð»Ñ ÑабоÑÑ Ñ Ð±Ð°Ð·Ð°Ð¼Ð¸ даннÑÑ Ð² Python. Ðни не имеÑÑ Ð½Ð¸Ñего обÑего, кÑоме имени.
43.7.2. ÐбÑабоÑка оÑибок
ФÑнкÑии, обÑаÑаÑÑиеÑÑ Ðº базе даннÑÑ
, могÑÑ ÑÑалкиваÑÑÑÑ Ñ Ð¾Ñибками, в ÑезÑлÑÑаÑе коÑоÑÑÑ
они бÑдÑÑ Ð¿ÑеÑÑваÑÑÑÑ Ð¸ вÑзÑваÑÑ Ð¸ÑклÑÑение. Ðбе ÑÑнкÑии plpy.execute и plpy.prepare могÑÑ Ð²ÑзÑваÑÑ ÑкземплÑÑ Ð¿Ð¾Ð´ÐºÐ»Ð°ÑÑа иÑклÑÑÐµÐ½Ð¸Ñ plpy.SPIError, коÑоÑое по ÑмолÑание пÑекÑаÑÐ°ÐµÑ Ð²Ñполнение ÑÑнкÑии. ÐÑÑ Ð¾ÑÐ¸Ð±ÐºÑ Ð¼Ð¾Ð¶Ð½Ð¾ обÑабоÑаÑÑ, как и лÑбое дÑÑгое иÑклÑÑение в Python, пÑименив конÑÑÑÑкÑÐ¸Ñ try/except. ÐапÑимеÑ:
CREATE FUNCTION try_adding_joe() RETURNS text AS $$
try:
plpy.execute("INSERT INTO users(username) VALUES ('joe')")
except plpy.SPIError:
return "something went wrong"
else:
return "Joe added"
$$ LANGUAGE plpythonu;ФакÑиÑеÑкий клаÑÑ Ð²ÑзÑваемого иÑклÑÑÐµÐ½Ð¸Ñ ÑооÑвеÑÑÑвÑÐµÑ Ð¾Ð¿ÑеделÑÐ½Ð½Ð¾Ð¼Ñ ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ Ð¾Ñибки. СпиÑок вÑÐµÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½ÑÑ ÑÑловий пÑиведÑн в ТаблиÑе A-1. РмодÑле plpy.spiexceptions опÑеделÑÑÑÑÑ ÐºÐ»Ð°ÑÑÑ Ð¸ÑклÑÑений Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑÑÐ»Ð¾Ð²Ð¸Ñ PostgreSQL, Ñ Ð¸Ð¼ÐµÐ½Ð°Ð¼Ð¸, пÑоизводнÑми Ð¾Ñ Ð¸Ð¼Ñн ÑÑловий. ÐапÑимеÑ, Ð¸Ð¼Ñ division_by_zero ÑÑановиÑÑÑ Ð¸Ð¼ÐµÐ½ÐµÐ¼ DivisionByZero, unique_violation â именем UniqueViolation, fdw_error â именем FdwError и Ñ. д. ÐÑе ÑÑи клаÑÑÑ Ð¸ÑклÑÑений наÑледÑÑÑÑÑ Ð¾Ñ SPIError. Такое Ñазделение на клаÑÑÑ ÑпÑоÑÐ°ÐµÑ Ð¾Ð±ÑабоÑÐºÑ Ð¾Ð¿ÑеделÑннÑÑ Ð¾Ñибок, напÑимеÑ:
CREATE FUNCTION insert_fraction(numerator int, denominator int) RETURNS text AS $$
from plpy import spiexceptions
try:
plan = plpy.prepare("INSERT INTO fractions (frac) VALUES ($1 / $2)", ["int", "int"])
plpy.execute(plan, [numerator, denominator])
except spiexceptions.DivisionByZero:
return "denominator cannot equal zero"
except spiexceptions.UniqueViolation:
return "already have that fraction"
except plpy.SPIError, e:
return "other error, SQLSTATE %s" % e.sqlstate
else:
return "fraction inserted"
$$ LANGUAGE plpythonu;ÐамеÑÑÑе, ÑÑо Ñак как вÑе иÑклÑÑÐµÐ½Ð¸Ñ Ð¸Ð· модÑÐ»Ñ plpy.spiexceptions наÑледÑÑÑÑÑ Ð¾Ñ Ð¸ÑклÑÑÐµÐ½Ð¸Ñ SPIError, команда except, обÑабаÑÑваÑÑÐ°Ñ ÑÑо иÑклÑÑение, бÑÐ´ÐµÑ Ð¿ÐµÑÐµÑ Ð²Ð°ÑÑваÑÑ Ð²Ñе оÑибки пÑи обÑаÑении к базе даннÑÑ .
РкаÑеÑÑве дÑÑгого ваÑианÑа обÑабоÑки ÑазлиÑнÑÑ ÑÑловий оÑибок, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе пеÑÐµÑ Ð²Ð°ÑÑваÑÑ Ð¸ÑклÑÑение SPIError и опÑеделÑÑÑ ÐºÐ¾Ð½ÐºÑеÑное ÑÑловие оÑибки внÑÑÑи блока except по знаÑÐµÐ½Ð¸Ñ Ð°ÑÑибÑÑа sqlstate обÑекÑа иÑклÑÑениÑ. ÐÑÐ¾Ñ Ð°ÑÑибÑÑ ÑодеÑÐ¶Ð¸Ñ ÑÑÑÐ¾ÐºÑ Ñ ÐºÐ¾Ð´Ð¾Ð¼ оÑибки "SQLSTATE". ÐонеÑнÑй ÑезÑлÑÑÐ°Ñ Ð¿Ñи Ñаком Ð¿Ð¾Ð´Ñ Ð¾Ð´Ðµ пÑимеÑно ÑÐ¾Ñ Ð¶Ðµ.
| ÐÑед. | ÐаÑало | След. |
| ТÑиггеÑнÑе ÑÑнкÑии | УÑÐ¾Ð²ÐµÐ½Ñ Ð²ÑÑе | ÐеÑвнÑе подÑÑанзакÑии |