วิธีสร้างสคริปต์ประมวลผล QGIS ที่เพิ่มลำดับลงในคอลัมน์ตัวระบุที่ไม่ซ้ำกันใน PostGIS


10

ใครสามารถช่วยฉันสร้างสคริปต์ประมวลผล QGIS ที่เพิ่มลำดับลงในคอลัมน์ตัวระบุที่มีอยู่ (ประเภท: จำนวนเต็ม) ใน PostGIS ได้หรือไม่

นี้จะเป็นประโยชน์มากเช่นเป็นวิธีแก้ปัญหาสำหรับข้อผิดพลาด# 6798 น่าเสียดายที่ฉันไม่มีประสบการณ์ Python เลย

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

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
ฉันจะถามว่าทำไมในเวิร์กโฟลว์ของคุณและเวิร์กโฟลว์ที่อธิบายไว้ในข้อผิดพลาดคุณไม่ได้จัดการข้อมูล PostgreSQL ของคุณโดยใช้ PGAdmin หรือเครื่องมือผู้ดูแลระบบหลักอื่น ๆ สำหรับ postgresql ฉันไม่รู้ว่าทำไมมีความพยายามในการใช้งานนี้ใน QGIS เมื่อเครื่องมือการดูแลระบบทำได้ดี!
DPSSpatial

สำหรับฉันการจัดการตารางใน QGIS DB-Manager นั้นค่อนข้างใช้งานง่าย อย่างไรก็ตามฉันสนใจที่จะดูว่าสคริปต์การประมวลผลสามารถเรียกใช้การสืบค้น PostGIS ได้อย่างไร
eclipsed_by_the_moon

3
สำหรับเรา PGAdmin และหน้าต่าง SQL เป็น "GIS" ของเรามากกว่า QGIS! QGIS เป็นเพียงไคลเอนต์ที่มองเห็นข้อมูลเชิงพื้นที่และผลลัพธ์ของเรา - งานทั้งหมดรวมถึง 'การประมวลผลทางภูมิศาสตร์, สคริปต์, ฯลฯ ถูกทำนอก QGIS ... เครื่องมือที่มีอยู่ในการทำสิ่งนี้ได้ถูกทำให้สมบูรณ์แล้วและจริงๆ เวิร์กโฟลว์ของการใช้เครื่องมือที่ไม่ใช่ QGIS เหล่านี้พร้อมกับข้อมูล PostgresSQL / PostGIS เป็นวิธีปฏิบัติที่ดีกว่า ...
DPSSpatial

คำตอบ:


2

เป็นที่น่าสังเกตว่าโมดูลหลามpsycopg2ดูเหมือนจะไม่COMMITทำธุรกรรมโดยอัตโนมัติ(เช่นลูกค้าอื่น ๆ เช่นผู้จัดการ QGIS DB หรือ pgAdmin ทำ) ดังนั้นCOMMITคำสั่งจะต้องเป็นส่วนหนึ่งของsqlสตริงในสคริปต์

นี้ไม่สำคัญกับSELECTงบเพราะในกรณีวิทยานิพนธ์จะดำเนินการอย่างเห็นได้ชัดออกมาเมื่อได้รับผลผ่านทางCOMMITcur.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 ของคุณสร้างผลลัพธ์ที่ถูกต้องสคริปต์ด้านล่างควรทำสิ่งที่คุณเป็น น่าเสียดายที่ฉันไม่มีอะไรมาทดสอบ แต่คุณสามารถลองและให้ข้อเสนอแนะ

ฉันพยายามแสดงความคิดเห็นเพื่อความสะดวกโดยพื้นฐานแล้วสคริปต์ดำเนินการสามขั้นตอน:

  • รับพารามิเตอร์การเชื่อมต่อฐานข้อมูลสำหรับเลเยอร์ที่เลือก (ควรเป็น 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

ขอบคุณสำหรับการแก้ไขปัญหานี้ แต่ฉันได้รับข้อผิดพลาด 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 ที่ไม่ซ้ำกันใหม่สำหรับคุณแทนที่จะสร้างลำดับ)

สิ่งนี้จะถือว่าคุณมีฟิลด์รหัสที่ไม่ซ้ำกัน (ซึ่งไม่จำเป็นต้องเป็นตัวเลข) แต่ต้องการรหัสตัวเลขแบบง่ายแทน (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.