PostGIS의 고유 식별자 열에 시퀀스를 추가하는 QGIS 처리 스크립트를 만드는 방법은 무엇입니까?


10

PostGIS의 기존 고유 식별자 열 (유형 : 정수)에 시퀀스를 추가하는 QGIS 처리 스크립트를 만들 수 있습니까?

예를 들어 버그 # 6798에 대한 해결 방법으로 매우 유용 합니다. 불행히도, 나는 파이썬 경험이 없습니다.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

CREATE SEQUENCE /*input_schema*/./*input_table*/_/*uic*/_seq OWNED BY /*input_schema*/./*input_table*/./*uic*/;
SELECT SETVAL('/*input_schema*/./*input_table*/_/*uic*/_seq', (SELECT MAX(/*uic*/) FROM /*input_schema*/./*input_table*/));
ALTER TABLE /*input_schema*/./*input_table*/
ALTER COLUMN /*uic*/ SET DEFAULT nextval('/*input_schema*/./*input_table*/_/*uic*/_seq'::regclass);

1
워크 플로 및 버그에 설명 된 워크 플로에서 왜 PGAdmin 또는 postgresql의 다른 핵심 관리 도구를 사용하여 PostgreSQL 데이터를 관리하고 있지 않습니까? 관리 도구가 제대로 작동 할 때 QGIS에서이 작업을 수행하는 데 왜 노력이 필요한지 모르겠습니다!
— DPSSpatial

나에게 QGIS DB-Manager의 테이블 관리는 매우 직관적입니다. 그러나 처리 스크립트가 PostGIS 쿼리를 실행하는 방법에 대해서도 관심이 있습니다.
— eclipsed_by_the_moon

3
우리에게 PGAdmin과 SQL 창은 QGIS보다 "GIS"에 가깝습니다! QGIS는 공간 데이터 및 출력에 대한 시각적 클라이언트 일뿐입니다. 'geo'처리, 스크립트 등을 포함한 모든 작업은 QGIS 외부에서 수행됩니다.이를 위해 존재하는 도구는 이미 완벽하며, PostgresSQL / PostGIS 데이터와 함께 비 QGIS 도구를 사용하는 워크 플로우는 더 나은 방법입니다.
— DPSSpatial

답변:


2

파이썬 모듈 psycopg2은 COMMITQGIS DB Manager 또는 pgAdmin과 같은 다른 클라이언트처럼 자동 으로 트랜잭션을 처리 하지 않는 것으로 보이 므로 COMMIT명령문은 sql스크립트 에서 문자열의 일부 여야 합니다.

이 SELECT경우에는를 COMMIT통해 결과를 얻을 때 분명히 수행 되기 때문에 이것은 진술 과 관련이 없습니다 cur.fetchall().

이것은 위의 답변에서 수정 된 스크립트 버전입니다.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

#--------- define Interface
##[my_scripts]=group
##Add Serial to PostgreSQL Table=name
##Postgres_Table=vector
##Unique_identifier_column=field Postgres_Table

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import *

from qgis.core import *
from qgis.gui import *
from qgis.utils import *

import psycopg2

#get the parameters for the tpg table into a directory
#get the table
pg_table = processing.getObject(Postgres_Table)
#create empty dictionary for key/value pairs of the tables connection parameters
db_params = {}
db_params['uic'] = Unique_identifier_column
#iterate over connection string
progress.setInfo(20*'-' + '  Connection parameters')
for param in pg_table.dataProvider().dataSourceUri().split(' '):
    key_val = param.split('=')
    progress.setInfo(str(key_val))
    try:
        #set key/value pair
        db_params[key_val[0]] = key_val[1]
    except:
        pass

#generate the sql statement string
#the text in round brackets are the keys from the db_params dictionary created above
#the values belonging to the keys are inserted into the string
progress.setInfo(20*'-' + '  SQL statement')
sql = """CREATE SEQUENCE %(table)s_%(uic)s_seq OWNED BY %(table)s.%(uic)s;
SELECT SETVAL('%(table)s_%(uic)s_seq', (SELECT MAX(%(uic)s) FROM %(table)s)); 
ALTER TABLE %(table)s ALTER COLUMN %(uic)s SET DEFAULT nextval('%(table)s_%(uic)s_seq'::regclass);
COMMIT;""" % db_params
#remove double quotes
sql = sql.replace('"','') 
progress.setInfo(sql)

#make connection string
constr = """dbname=%(dbname)s host=%(host)s port=%(port)s user=%(user)s     password=%(password)s""" % db_params
progress.setInfo(20*'-' + '  DB Connection string')
progress.setInfo(constr)
#make db connection
con = psycopg2.connect(constr)
cur = con.cursor()
#execute the above created sql statement
progress.setInfo(20*'-' + '  Executing SQL statement ...')
cur.execute(sql)
progress.setInfo(20*'-' + '  ... done.')

6

SQL 문이 유효한 결과를 생성하면 아래 스크립트가 수행 한 작업을 수행해야합니다. 불행히도 이것을 테스트 할 수있는 것은 없지만 피드백을 줄 수 있습니다.

편의상 주석 처리를 시도했지만 기본적으로 스크립트는 3 단계를 수행합니다.

  • 선택한 레이어에 대한 데이터베이스 연결 매개 변수를 얻습니다 (postgres 여야 함).
  • SQL 문 문자열의 연결 매개 변수를 채 웁니다.
  • SQL 문을 실행

스크립트의 프로토콜 출력에 유의하십시오.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

#--------- define Interface
##[my_scripts]=group
##Add Serial to PostgreSQL Table=name
##Postgres_Table=vector
##Unique_identifier_column=string replace_this_with_your_uic

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import *

from qgis.core import *
from qgis.gui import *
from qgis.utils import *

import psycopg2

#get the parameters for the tpg table into a directory
#get the table
pg_table = processing.getObject(Postgres_Table)
#create empty dictionary for key/value pairs of the tables connection parameters
db_params = {}
db_params['uic'] = Unique_identifier_column
#iterate over connection string
progress.setInfo(20*'-' + '  Connection parameters')
for param in pg_table.dataProvider().dataSourceUri().split(' '):
    key_val = param.split('=')
    progress.setInfo(str(key_val))
    try:
        #set key/value pair
        db_params[key_val[0]] = key_val[1]
    except:
        pass

#generate the sql statement string
#the text in round brackets are the keys from the db_params dictionary created above
#the values belonging to the keys are inserted into the string
progress.setInfo(20*'-' + '  SQL statement')
sql = """CREATE SEQUENCE %(table)s_%(uic)s_seq OWNED BY %(table)s.%(uic)s;
            SELECT SETVAL(%(table)s_%(uic)s_seq, (SELECT MAX(%(uic)s) FROM %(table)s));
            ALTER TABLE %(table)s
            ALTER COLUMN %(uic)s SET DEFAULT nextval(%(table)s_%(uic)s_seq::regclass);""" % db_params
#remove double quotes
sql = sql.replace('"','') 
progress.setInfo(sql)

#make connection string
constr = """dbname=%(dbname)s host=%(host)s port=%(port)s user=%(user)s     password=%(password)s""" % db_params
progress.setInfo(20*'-' + '  DB Connection string')
progress.setInfo(constr)
#make db connection
con = psycopg2.connect(constr)
cur = con.cursor()
#execute the above created sql statement
progress.setInfo(20*'-' + '  Executing SQL statement ...')
cur.execute(sql)
progress.setInfo(20*'-' + '  ... done.')

스크립트를 테스트했으며 처리 로그에라고 말합니다 unexpected indent (, line 32) See log for more details. 내가 잘못하고있는 것이 있습니까? SQL 문이 DB-Manager에서 작동 중입니다.
— eclipsed_by_the_moon

File "C:/Users/abc/.qgis2/python/plugins\processing\core\GeoAlgorithm.py", line 230, in execute self.processAlgorithm(progress) File "C:/Users/abc/.qgis2/python/plugins\processing\script\ScriptAlgorithm.py", line 298, in processAlgorithm exec((script), ns) File "<string>", line 32 try: ^
— eclipsed_by_the_moon

그래, 내 잘못이야 try문은 잘못 들여 쓰기를했다. 방금 수정했습니다.
— Jochen Schwarze

이 문제를 해결하기위한 Thx이지만 스크립트를 실행할 때 Python 오류가 발생합니다.
— eclipsed_by_the_moon

Traceback (most recent call last): File "C:/Users/abc/.qgis2/python/plugins\processing\gui\AlgorithmDialog.py", line 219, in accept if runalg(self.alg, self): File "C:/Users/abc/.qgis2/python/plugins\processing\gui\AlgorithmExecutor.py", line 51, in runalg alg.execute(progress) File "C:/Users/abc/.qgis2/python/plugins\processing\core\GeoAlgorithm.py", line 244, in execute unicode(e) + self.tr('\nSee log for more details')) UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 44: ordinal not in range(128)
— eclipsed_by_the_moon

3

이미 비슷한 플러그인이있는 것 같습니다 ( 시퀀스를 생성하는 대신 새로운 고유 ID 필드를 생성하더라도 ).

이것은 이미 고유 한 id 필드를 가지고 있다고 가정 하지만 (숫자가 될 필요는 없음) 대신 간단한 숫자 ID를 원합니다 (1,2,3.)

처리 도구 상자에서 스크립트> 도구> 온라인에서 스크립트 가져 오기 ...로 이동하십시오.

"설치되지 않음"을 펼치고 "EquivalentNumField"를 선택하십시오. 확인을 클릭하기 전에 확인란을 클릭해야합니다. 그것은 나를 잡았다 ... ;-)

여기에 이미지 설명을 입력하십시오

빨리 찾으려면 처리 검색 표시 줄에 "Equiv"를 입력하면 거기서 두 번 클릭 할 수 있습니다.

여기에 이미지 설명을 입력하십시오

다음은 예입니다. 이 숲에는 고유 필드 (osm_id)가 있었지만 플러그인은 간단한 숫자 값으로 NUM_FIELD를 추가했습니다.

여기에 이미지 설명을 입력하십시오


스티브, 이것은 유용한 스크립트이지만 다른 것을 찾고 있습니다.
— eclipsed_by_the_moon

@eclipsed_by_the_moon이 답변이 당신이 찾고있는 것과 어떻게 다른가요? 고유 식별자 열이 필요한 문제를 궁극적으로 해결하는 것으로 보입니다.
— kttii
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.