如何创建将序列添加到PostGIS中唯一标识符列的QGIS处理脚本?


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
我想问为什么在您的工作流程以及错误中描述的工作流程中,您没有使用PGAdmin或其他用于PostgreSQL的核心管理工具来管理PostgreSQL数据?我不知道为什么只要管理工具就可以在QGIS上花点功夫!
DPSSpatial '16

对我而言,在QGIS DB-Manager中管理表非常直观。但是,我也很想看看处理脚本如何运行PostGIS查询。
eclipsed_by_the_moon

3
对我们来说,PGAdmin和SQL窗口比QGIS更像是我们的“ GIS”!QGIS只是我们空间数据和输出的可视化客户端-所有工作,包括“地理”处理,脚本等,都是在QGIS之外完成的。将这些非QGIS工具与PostgresSQL / PostGIS数据一起使用的工作流程是更好的做法...
DPSSpatial 2016年

Answers:


2

值得注意的是,python模块psycopg2似乎并不自动COMMIT进行事务处理(就像QGIS DB Manager或pgAdmin之类的其他客户端一样),因此该COMMIT语句必须是sql脚本中字符串的一部分。

这与SELECT语句无关紧要,因为在这些情况下COMMIT,显然通过a 获得结果时执行a 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语句产生有效的结果,则下面的脚本应该可以完成您的工作。不幸的是,我没有任何东西可以测试这一点,但是您可以尝试并提供反馈。

为了方便起见,我尝试对其进行注释,基本上该脚本执行三个步骤:

  • 获取所选图层的数据库连接参数(应为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字段,而不是创建一个序列。)

假设您已经有一个唯一的ID字段(不需要数字),但是想要一个简单的数字ID(1,2,3 ..)

在处理工具箱中,转到脚本>工具>从在线获取脚本...

展开“未安装”,然后选择“ EquivalentNumField”。请记住在单击确定之前先单击复选框。那把我吸引了... ;-)

在此处输入图片说明

为了快速找到它,在处理搜索栏中键入“ Equiv”,您应该能够从那里双击它。

在此处输入图片说明

这是一个例子。这些树林有一个唯一的字段(osm_id),但该插件添加了一个NUM_FIELD和简单的数值

在此处输入图片说明


史蒂夫,这是一个有用的脚本,但是我正在寻找与众不同的东西。
eclipsed_by_the_moon 2016年

@eclipsed_by_the_moon这个答案不是您想要的吗?它似乎最终解决了您需要唯一标识符列的问题。
kttii '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.