Команда PostgreSQL EXECUTE успешно выполнена, но в таблице нет изменений - PullRequest
0 голосов
/ 06 сентября 2011

У меня есть следующий скрипт PostgreSQL:

    CREATE OR REPLACE FUNCTION merge_fields() RETURNS VOID AS $$
     DECLARE
        current_record airport%ROWTYPE;
        new_record airport%ROWTYPE;
        column_def RECORD;
        old_value TEXT;
        new_value TEXT;
        field_name TEXT;
        sql_text  TEXT;
        integer_var INT;

     BEGIN       

        FOR current_record in SELECT * FROM airport LOOP

        -- Match Record based on iko and modified time
          SELECT * INTO new_record FROM airport WHERE 
              iko = current_record.iko AND mod_time > current_record.mod_time;             
          IF FOUND THEN 
            FOR column_def IN 

                    -- Get fields for this record
                SELECT ordinal_position, column_name, data_type 
                FROM information_schema.columns  
                WHERE 
                        table_schema = 'public' 
                AND     table_name = 'airport' 
                ORDER BY ordinal_position
                LOOP                                                

                    field_name := column_def.column_name;
                    IF ((field_name = 'gid') OR (field_name = 'mod_time')) THEN                             
                    ELSE    

-- Get each field value for current and new record.  New record is matched record.                                  
                        EXECUTE 'SELECT ($1).' || field_name || '::' || column_def.data_type INTO old_value USING current_record;
                        EXECUTE 'SELECT ($1).' || field_name || '::' || column_def.data_type INTO new_value USING new_record;                                       

                        IF new_value IS NOT NULL THEN               
                            IF new_value <> old_value THEN

                            sql_text := 'UPDATE ' || 'airport' 
                                    || ' SET '
                                    || quote_ident(field_name)
                                    || ' = ' 
                                    || quote_literal(new_value) 
                                    || ' WHERE gid = '
                                    || current_record.gid;


    -- Set current record field value same as new record field value
                                      EXECUTE 'UPDATE ' || 'airport' 
                                    || ' SET '
                                    || quote_ident(field_name)
                                    || ' = ' 
                                    || quote_nullable(new_value) 
                                    || ' WHERE gid = '
                                    || current_record.gid;

                            GET DIAGNOSTICS integer_var = ROW_COUNT;                        
                            RAISE NOTICE E'Old Value\t   rows affected: %\t ',integer_var;  

                                RAISE NOTICE E'Old Value\t   name: %\t   value: %.\n',          
                                    field_name,         
                                    old_value;                                                      
                                RAISE NOTICE E'New Value\t   name: %\t   value: %.\n',          
                                    field_name,         
                                    new_value;                                                                  

                            END IF;
                        END IF;

                    END IF; 

                -- End column enumerating loop
                 END LOOP;  


          END IF;
          IF NOT FOUND THEN        
          END IF;

        END LOOP;    

        EXCEPTION
            WHEN TOO_MANY_ROWS THEN
                     RAISE NOTICE E'Too many records match search criteria.';   
            WHEN OTHERS THEN
           --     RAISE EXCEPTION 'airports % not found';              
     END;
    $$
    LANGUAGE plpgsql;

Я пытаюсь объединить две записи в таблице базы данных на основе измененного времени. Что скрипт делает следующим образом:

Для каждой записи в таблице я нахожу все соответствующие записи по ключевому полю с именем "iko" с изменено время позже текущей записи.

Будет один или нет совпадений. Если совпадение найдено, я перечисляю каждое поле в текущей и совпадающей записи и синхронизирую поля, если последнее не равно нулю.

Скрипт работает как положено, без ошибок. Кроме того, результат диагностики ROW_COUNT указывает, что 1 строка обновлена ​​после вызова команды EXECUTE в сценарии. Однако, когда я обновляю таблицу, я не вижу ожидаемого изменения.

Есть идеи, почему?

ТИА.

1 Ответ

0 голосов
/ 08 сентября 2011

Изменения были внесены в таблицу успешно, как указано, но из-за ошибки в скрипте, когда я пытался назначить не-TEXT типы данных для переменной TEXT, возникало исключение, вызывая откат транзакции. Это где сценарий терпит неудачу, если значение поля записи не TEXT.:

-- Get each field value for current and new record.  New record is matched record.                                  
                        EXECUTE 'SELECT ($1).' || field_name || '::' || column_def.data_type INTO old_value USING current_record;
                        EXECUTE 'SELECT ($1).' || field_name || '::' || column_def.data_type INTO new_value USING new_record;  

где old_value и new_value - переменные TEXT, объявленные ранее в скрипте.

Если имя столбца известно, можно объявить переменную, например

 var_name table_name.column_name%TYPE; 

, который будет динамически содержать любой тип данных. Поскольку имя столбца обнаруживается динамически, такая переменная не может быть использована. Я не мог придумать, как легко это сделать, поэтому выбрал совершенно другую стратегию.

...