2011-09-06 51 views
0

我有以下的PostgreSQL腳本沒有變化:PostgreSQL的EXECUTE命令的成功,但在表

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命令之後。但是,當我刷新表格時,我看不到預期的變化。

任何想法爲什麼?

TIA。

+1

你在交易中使用它嗎?如果是,你有沒有改變? –

+0

是的,我在交易中使用它。但是,事務正在被回滾,因爲在腳本中引發了異常。由於所有字段都不是TEXT,所以會引發異常,所以片段很麻煩。 –

回答

0

如表所示,對錶成功進行了更改,但由於腳本中的錯誤,我試圖將非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是早先在腳本中聲明的文本變量。

如果列名稱是已知的,人們可以將一個變量聲明如

var_name table_name.column_name%TYPE; 

這將動態地保持任何數據類型。因爲列名是動態發現的,所以不能使用這樣的變量。我想不出一種方法來輕鬆實現這一點,所以我選擇了一種完全不同的策略。

相關問題