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

파이썬 모듈 psycopg2COMMITQGIS 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.