Làm cách nào để tạo tập lệnh xử lý QGIS thêm chuỗi vào cột định danh duy nhất trong PostGIS?


10

Ai đó có thể giúp tôi tạo tập lệnh xử lý QGIS thêm chuỗi vào cột định danh duy nhất hiện có (loại: số nguyên) trong PostGIS không?

Điều này sẽ khá hữu ích, ví dụ như một cách giải quyết cho lỗi # 6798 . Thật không may, tôi không có bất kỳ kinh nghiệm Python.

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

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
Tôi sẽ hỏi tại sao trong quy trình làm việc của bạn và quy trình công việc được mô tả trong lỗi, bạn không quản lý dữ liệu PostgreQuery của mình bằng PGAdmin hoặc các công cụ quản trị cốt lõi khác cho postgresql? Tôi không biết tại sao có nỗ lực dành cho việc này hoạt động trong QGIS khi các công cụ quản trị làm việc đó tốt!
DPSSpatial

Đối với tôi, việc quản lý các bảng trong Trình quản lý DBIS là khá trực quan. Tuy nhiên, tôi cũng muốn xem làm thế nào một tập lệnh xử lý có thể chạy các truy vấn PostGIS.
lu mờ_by_the_moon

3
Đối với chúng tôi, PGAdmin và cửa sổ SQL là "GIS" của chúng tôi nhiều hơn so với QGIS! QGIS chỉ là ứng dụng khách trực quan cho dữ liệu không gian và đầu ra của chúng tôi - tất cả công việc, bao gồm 'xử lý địa lý, tập lệnh, v.v. được thực hiện bên ngoài QGIS ... các công cụ tồn tại để thực hiện điều này đã được hoàn thiện và thực sự, quy trình sử dụng các công cụ không phải là QGIS này với dữ liệu PostgresSQL / PostGIS là cách thực hành tốt hơn ...
DPSSpatial

Câu trả lời:


2

Điều đáng chú ý là mô-đun python psycopg2dường như không tự động COMMITgiao dịch (như các máy khách khác như QGIS DB Manager hoặc pgAdmin làm), do đó, COMMITcâu lệnh phải là một phần của sqlchuỗi trong tập lệnh.

Điều này không quan trọng với các SELECTtuyên bố vì trong các trường hợp này, a COMMITrõ ràng được thực hiện khi nhận được kết quả thông qua cur.fetchall().

Đây là phiên bản được làm lại của tập lệnh từ câu trả lời của tôi ở trên:

#!/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

Với điều kiện câu lệnh SQL của bạn tạo ra kết quả hợp lệ, các tập lệnh bên dưới sẽ thực hiện những gì bạn đang theo sau. Thật không may, tôi không có gì để kiểm tra điều này, nhưng bạn có thể thử và đưa ra phản hồi.

Tôi đã cố gắng bình luận nó cho thuận tiện, về cơ bản kịch bản thực hiện ba bước:

  • có được các tham số kết nối cơ sở dữ liệu cho lớp đã chọn (nên là postgres)
  • điền các tham số kết nối trong chuỗi câu lệnh sql
  • thực hiện câu lệnh sql

Lưu ý đầu ra giao thức của tập lệnh.

#!/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.')

Tôi đã kiểm tra tập lệnh và nhật ký xử lý nói unexpected indent (, line 32) See log for more details. Có điều gì đó tôi đang làm sai? Câu lệnh SQL đang làm việc trong Trình quản lý DB.
lu mờ_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: ^
lu mờ_by_the_moon

Đúng, lỗi của tôi. Các trytuyên bố đã thụt sai. Chỉ cần sửa lỗi này.
Jochen Schwarze

Thx đã sửa lỗi này, nhưng tôi gặp lỗi Python khi chạy tập lệnh.
lu mờ_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)
lu mờ_by_the_moon

3

Dường như đã có một plugin tương tự (mặc dù nó tạo ra một trường ID duy nhất mới cho bạn, thay vì tạo một chuỗi.)

Điều này giả sử bạn đã có một trường id duy nhất (cái này không cần phải là số), nhưng muốn có một ID số đơn giản thay vào đó (1,2,3 ..)

Trong hộp công cụ Xử lý, đi tới Tập lệnh> Công cụ> Nhận tập lệnh từ Trực tuyến ...

Mở rộng "Chưa cài đặt" và chọn "EquivalentNumField". Nhớ nhấp vào hộp kiểm trước khi nhấp vào OK. Điều đó bắt tôi ra ... ;-)

nhập mô tả hình ảnh ở đây

Để tìm thấy nó một cách nhanh chóng, nhập "Equiv" vào thanh tìm kiếm xử lý và bạn sẽ có thể nhấp đúp vào nó từ đó.

nhập mô tả hình ảnh ở đây

Đây là một ví dụ. Các loại gỗ này có một trường duy nhất (osm_id) nhưng plugin đã thêm NUM_FIELD với các giá trị số đơn giản thay thế

nhập mô tả hình ảnh ở đây


Steve, đây là một kịch bản hữu ích, nhưng tôi đang tìm kiếm một cái gì đó khác biệt.
lu mờ_by_the_moon

@eclipsed_by_the_moon làm thế nào câu trả lời này không phải là những gì bạn đang tìm kiếm? Nó xuất hiện để giải quyết cuối cùng vấn đề của bạn về việc cần một cột định danh duy nhất.
kttii
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.