Як створити скрипт обробки 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, коли інструменти адміністрування роблять це чудово!
DPSSpace

Для мене керування таблицями в QGIS DB-Manager досить інтуїтивно зрозуміле. Однак мені також цікаво подивитися, як сценарій обробки може запускати запити PostGIS.
eclipsed_by_the_moon

3
Для нас PGAdmin і вікно SQL - це більше наш "ГІС", ніж QGIS! QGIS є лише візуальним клієнтом наших просторових даних та результатів - вся робота, включаючи "гео'-обробку, сценарії тощо) проводиться поза QGIS ... інструменти, які існують для цього, вже вдосконалені, і справді, робочий процес використання цих інструментів, що не належать до QGIS, з даними PostgresSQL / PostGIS - це краща практика ...
DPSSpatial

Відповіді:


2

Варто зазначити, що модуль python psycopg2не здається автоматично COMMITтрансакцією (як це роблять інші клієнти, такі як QGIS DB Manager або pgAdmin), тому COMMITоператор повинен бути частиною sqlрядка в скрипті.

Це не має значення для SELECTтверджень, оскільки у випадках тез a 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 дає справжні результати, нижче наведені сценарії повинні робити те, що ви хочете. На жаль, у мене немає нічого для того, щоб перевірити це, але ви можете спробувати і дати відгук.

Я намагався прокоментувати це для зручності, в основному сценарій виконує три дії:

  • отримання параметрів підключення до бази даних для вибраного шару (має бути постгрес)
  • заповніть параметри з'єднання в рядку заяви 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 працює в менеджері БД.
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заяві було неправильне відступ. Просто виправили це.
Йохен Шварце

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

Здається, вже є подібний плагін (хоча він створює нове унікальне поле для ідентифікатора, а не створює послідовність.)

Це передбачає, що у вас вже є унікальне поле ідентифікатора (це не потрібно, щоб було числовим), але ви хочете отримати простий числовий ідентифікатор (1,2,3 ..)

У панелі інструментів "Обробка" перейдіть до Сценарії> Інструменти> Отримати сценарії з Інтернету ...

Розгорніть "Не встановлено" та виберіть "ЕквівалентнеNumField". Не забудьте встановити прапорець перед тим, як натиснути кнопку ОК. Це мене зловило ... ;-)

введіть тут опис зображення

Щоб швидко знайти його, введіть "Equiv" на панелі пошуку обробки, і ви повинні мати можливість двічі клацнути по ньому.

введіть тут опис зображення

Ось приклад. Ці ліси мали унікальне поле (osm_id), але плагін замість цього додав NUM_FIELD з простими числовими значеннями

введіть тут опис зображення


Стів, це корисний сценарій, але я шукаю щось інше.
eclipsed_by_the_moon

@eclipsed_by_the_moon як ця відповідь не те, що ти шукаєш? Здається, врешті-решт вирішити вашу проблему необхідності створення унікального стовпчика ідентифікатора.
kttii
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.