2017-04-11 1 views
0

stdin에서 줄을 읽으려고하고 plpythonu 저장 프로 시저를 사용하여 그 줄의 데이터를 PostgreSQL db에 삽입하려고합니다.이 plpythonu 저장 프로 시저를 데이터베이스에 삽입하려면 어떻게해야합니까?

파이썬 3에서 프로 시저를 호출하면 이 실행되지만 (각 행 읽기에 대해 일련 값 사용) db에는 데이터가 저장되지 않습니다. psql에서 같은 프로 시저를 호출하면 db에 한 줄만 삽입하면됩니다.

작업 : : 사용자로 psql의 내부에서 jazcap53
결과를 SELECT sl_insert_day('2017-01-02', '05:15');을 실행 예를를 들어

명령 줄
결과에 python3 src/load/load_mcv.py < input.txt을 실행 : 하루 1

액션 day_id 삽입하지 아무것도 삽입되었지만 2 serial_id가 소비되었습니다.

조치 : 사용자로 psql의 내부에서 jazcap53
결과를 SELECT sl_insert_day('2017-01-03', '06:15');을 실행 일 day_id 4.

파일 삽입 : input.txt를 :

DAY, 2017-01-05, 06:00 
DAY, 2017-01-06, 07:00 

출력 :

('sl_insert_day() succeeded',) 
('sl_insert_day() succeeded',) 

저는 Fedora 25, Python 3.6.0 및 PostgreSQL 9.5.6을 실행하고 있습니다.

도와 주실 수있는 분들께 고맙습니다!


다음은이 동작을 재현하는 MCV 예제입니다. 제 8 단계 또는 6 단계에서 문제가 발생할 것으로 예상됩니다. 다른 단계는 완전성을 위해 포함되어 있습니다. MCV를 만드는 데 사용

단계들은

단계 1) 데이터베이스의 생성 :

사용자 포스트 그레스 등 psql의에서는

데이터베이스를 만들 sl_test_mcv
;

2 단계) 데이터베이스 초기화 :

파일 :/database_mcv.ini DB

[postgresql] 
host=localhost 
database=sl_test_mcv 
user=jazcap53 
password=***** 

3 단계) 실행 데이터베이스 설정 :

파일 : DB/config_mcv.py

from configparser import ConfigParser 

def config(filename='db/database_mcv.ini', section='postgresql'): 
    parser = ConfigParser() 
    parser.read(filename) 
    db = {} 
    if parser.has_section(section): 
     params = parser.items(section) 
     for param in params: 
      db[param[0]] = param[1] 
    else: 
     raise Exception('Section {} not found in the {} file'.format(section, filename)) 
    return db 

4 단계) 테이블 만들기 :

파일 : db/create_tables_mcv.SQL

DROP TABLE IF EXISTS sl_day CASCADE; 

CREATE TABLE sl_day (
    day_id SERIAL UNIQUE, 
    start_date date NOT NULL, 
    start_time time NOT NULL, 
    PRIMARY KEY (day_id) 
); 

5 단계) 작성 언어 :

CREATE LANGUAGE plpythonu; 

6 단계) 작성 절차 :

파일 : DB/create_procedures_mcv.sql

DROP FUNCTION sl_insert_day(date, time without time zone); 

CREATE FUNCTION sl_insert_day(new_start_date date, 
    new_start_time time without time zone) RETURNS text AS $$ 
from plpy import spiexceptions 
try: 
    plan = plpy.prepare("INSERT INTO sl_day (start_date, start_time) \ 
      VALUES($1, $2)", ["date", "time without time zone"]) 
    plpy.execute(plan, [new_start_date, new_start_time]) 
except plpy.SPIError, e: 
    return "error: SQLSTATE %s" % (e.sqlstate,) 
else: 
    return "sl_insert_day() succeeded" 
$$ LANGUAGE plpythonu; 

7 단계)을 부여 권한 :

파일 : DB/grant_privileges_mcv.sql

GRANT SELECT, UPDATE, INSERT, DELETE ON sl_day TO jazcap53; 
GRANT USAGE ON sl_day_day_id_seq TO jazcap53; 

8 단계) python3의 SRC /로드/load_mcv.py으로 실행 절차 < input.txt를 :

파일 : SRC /로드/load_mcv.py

import sys 
import psycopg2 
from spreadsheet_etl.db.config_mcv import config 

def conn_exec(): 
    conn = None 
    try: 
     params = config() 
     conn = psycopg2.connect(**params) 
     cur = conn.cursor() 
     last_serial_val = 0 
     while True: 
      my_line = sys.stdin.readline() 
      if not my_line: 
       break 
      line_list = my_line.rstrip().split(', ') 
      if line_list[0] == 'DAY': 
       cur.execute('SELECT sl_insert_day(\'{}\', \'{}\')'. 
          format(line_list[1], line_list[2])) 
       print(cur.fetchone()) 
     cur.close() 
    except (Exception, psycopg2.DatabaseError) as error: 
     print(error) 
    finally: 
     if conn is not None: 
      conn.close() 

if __name__ == '__main__': 
    conn_exec() 

답변

1

do conn.commit()cur.close()

관련 문제