не замечать мусор в COPY

ГАГН 2
Дата: 02.11.2004 10:32:32
в системе есть определенный файл с набором данных,
содержимое которого, регулярно обновляясь, каждый раз заливается в таблицу

в данный файл в позиции для поля типа integer иногда приходит мусор
в виде текстовых значений и рвёт всю транзакцию

можно как-нибудь организовать игнорирование вставки неверных значений на уровне поля (вместо мусора пойдет 0 либо Null), либо на уровне записи (данная строчка просто не вставится в таблицу)?
ГАГН 2
Дата: 02.11.2004 10:52:33
сорри, Pg 7.4.1.
Niemi
Дата: 02.11.2004 12:24:01
Может я неверно понял, но можно поставить значение поля по умолчанию, либо сделать проверку при вводе поля. CHECK bla bla
ГАГН 2
Дата: 02.11.2004 13:42:39
Niemi
Может я неверно понял, но можно поставить значение поля по умолчанию, либо сделать проверку при вводе поля. CHECK bla bla


так ведь ни СНЕСК, ни значение по умолчанию не позволят "проглотить" неверные значения, процесс всё равно выдаст ошибку и завершит транзакцию откатом
wbear
Дата: 02.11.2004 14:55:04
в голову пришло несколько идей, но надо уточнить детали в доках посгреса(лично мне лень :)

1. в таблице у этого поля зделать собственный тип (CREATE TYPE), потом зделать касты text->тип и тип->int4 (CREATE CAST).. потом при использовании на забывать делать поле::int4

2. фильтрить файл например перловым скриптом перед занесением в базу.
4321
Дата: 02.11.2004 15:44:55
Лейте COPY в промежуточную таблу-корзину с полями text, а оттуда уже осуществляйте заливку с разбором значений и CAST-ингом.


_________
Подумал было, что RULE на INSERT (с разбором и подменой мусора умолчательными значениями) может помочь (если COPY не обходит RULE) обойтись без промежуточной корзинки. И если такое RULE допустимо "напостоянку" - т.е. не только для вливки данных (в этом случае можно бы было поробовать RULE на view) - АН ФИХ - COPY can only be used with plain tables, not with views). и даже: COPY FROM will invoke any triggers and check constraints on the destination table. However, it will not invoke rules.
Т.ч RULE отпадает.
ГАГН 2
Дата: 05.11.2004 08:49:45
4321
Лейте COPY в промежуточную таблу-корзину с полями text, а оттуда уже осуществляйте заливку с разбором значений и CAST-ингом.


а можно поподробнее остановиться на моменте разбора значений?
4321
Дата: 05.11.2004 12:06:03
ГАГН 2

а можно поподробнее остановиться на моменте разбора значений?


не понял, в чем проблема. Если в том, чтобы произвести CAST от всех подходящих значений text в требуемый тип - так при написании процедуры упирайте на SQL а не на plpgsql и отлаживайте куски - оно вам само сообщит, есть ли CAST от text к тому типу, к какому хотите. Если нет - сделайте цепочку кастов через промежуточные типы. (или напишите свои ф-ии).


Если же вы хотите обработать ошибку, боюсь ни в SQL транзакции, ни в plpgsql функции вы этого сегодня не сделаете:
PostgreSQL 7.4beta4 Documentation
Chapter 39. PL/pgSQL - SQL Procedural Language

Thus, the only thing PL/pgSQL currently does when it encounters an abort during execution of a function or trigger procedure is to add some fields to the message telling in which function and where (line number and type of statement) the error happened. The error always stops execution of the function.

я вижу только одну главу в документации, посвященную Error Handling
PostgreSQL 7.4beta4 Documentation
Chapter 30. ECPG - Embedded SQL in C
--------------------------------------------------------------------------------

30.9. Error Handling

А SQL транзакция однозначно потребует RallBack после первой же ошибки (не понимаю, почему тогда серверу не делать RallBack автоматом с закрытием транзакции и выдачей соответственного сообщения - чё ждать то, когда все остальное все равно запрещено? Удизм какой-то академический...)



Т.е. , в итоге, вы должны написать что-то вида
INSERT INTO ta_bla (f1,f2,f3...)
 SELECT f1::{typeof_f1}|MyFun(f1),f2::{typeof_f1}|..., FROM bufof_ta_bla
причем так, чтобы нигде не могло возникнуть ошибок при вставке.
Если не уверены в том, что перекрыли все возиможные источники ошибок при приведении данных (например констрайнты могут меняться), а вставлять хотя бы то, что вставится надо, то выход - в построчной вставке из любого внешнего инструмента, позволяющего обработку ошибок (т.е. INSERT INTO делаете для строки, и независимо от того вставилась/не вставилась - вставляете следущую, а "не вставку" суете в лог, для ручного разбора). Аналогом этого внешнего (по отношению к SQL) инструмента видимо может служить и C (не пользовался).
ГАГН 2
Дата: 05.11.2004 15:50:01
4321
не понял, в чем проблема. Если в том, чтобы произвести CAST от всех подходящих значений text в требуемый тип - так при написании процедуры упирайте на SQL а не на plpgsql и отлаживайте куски - оно вам само сообщит, есть ли CAST от text к тому типу, к какому хотите. Если нет - сделайте цепочку кастов через промежуточные типы. (или напишите свои ф-ии).


иными словами, в функции, насколько я понял, нужно обрабатывать входные значения..
нужно отделить числа от всего остального,
т.е. использовать регулярные выражения для фильтрации целых чисел

сверив с шаблоном (напр., "^\-?[0-9]+$") входное значение $1,
мы решаем, оставлять ли его как есть (т.е. на входе- число),
либо вставлять вместо него NULL (на входе мусор)

верно?
Shweik
Дата: 06.11.2004 11:00:36
IMHO внешний фильтр (perl/awk) причешет данные на порядок быстрее и красивей. "Пирог нужно есть вилкой" (с) Р.А Хайнлайн.