PostGIS'de benzersiz bir tanımlayıcı sütununa sıra ekleyen bir QGIS işleme komut dosyası nasıl oluşturulur?


10

Herhangi biri PostGIS'te mevcut benzersiz tanımlayıcı sütununa (type: integer) bir dizi ekleyen bir QGIS işleme komut dosyası oluşturmama yardımcı olabilir mi?

Bu oldukça yararlı olacaktır, örneğin hata # 6798 için bir geçici çözüm olarak . Ne yazık ki, herhangi bir Python deneyimim yok.

resim açıklamasını buraya girin

resim açıklamasını buraya girin

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
Neden iş akışınızda ve hatada açıklanan iş akışında, PGAdmin veya postgresql için diğer temel yönetici araçlarını kullanarak PostgreSQL verilerinizi yönetmediğinizi sorardım? Yönetici araçları işe yaradığında QGIS'te bu işi yapmak için neden çaba harcandığını bilmiyorum!
DPSSpatial

Bana göre, QGIS DB-Manager'daki tabloları yönetmek oldukça sezgisel. Ancak, bir işleme komut dosyasının PostGIS sorgularını nasıl çalıştırabileceğini de görmek istiyorum.
eclipsed_by_the_moon

3
Bizim için PGAdmin ve SQL penceresi QGIS'den daha çok "GIS" mizdir! QGIS, mekansal verilerimiz ve çıktılarımız için sadece görsel bir müşteridir - 'coğrafi' işleme, komut dosyaları vb. Dahil tüm işler QGIS dışında yapılır ... bunu yapmak için var olan araçlar zaten mükemmelleştirilmiştir ve gerçekten, bu QGIS olmayan araçları PostgresSQL / PostGIS verileriyle kullanma iş akışı daha iyi bir uygulamadır ...
DPSSpatial

Yanıtlar:


2

Python modülünün psycopg2otomatik olarak COMMITbir işlem (QGIS DB Manager veya pgAdmin gibi diğer istemciler gibi) gibi görünmediğini , bu nedenle COMMITifadenin koddaki sqldizenin bir parçası olması gerektiğini belirtmek gerekir .

Bu SELECTifadeler ile önemli değildir, çünkü bu durumlarda a COMMITsonuçları alırken açıkça yapılır cur.fetchall().

Bu, yukarıdaki cevabımdan komut dosyasının elden geçirilmiş bir sürümüdür:

#!/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 ifadenizin geçerli sonuçlar üretmesi şartıyla, aşağıdaki komut dosyaları peşinde olduklarınızı yapmalıdır. Maalesef bunu test etmek için elimde hiçbir şey yok, ancak geri bildirimde bulunmayı deneyebilirsin.

Kolaylık için yorum yapmaya çalıştım, temelde komut dosyası üç adım gerçekleştirir:

  • seçili katman için veritabanı bağlantı parametrelerini edinme (postgres olmalıdır)
  • sql ifade dizesindeki bağlantı parametrelerini doldurun
  • sql deyimini yürüt

Komut dosyasının protokol çıktısına dikkat edin.

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

Senaryoyu test ettim ve işlem günlüğü diyor unexpected indent (, line 32) See log for more details. Yanlış yaptığım bir şey var mı? SQL deyimi DB-Manager'da çalışıyor.
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

Evet, benim hatam. tryİfadesi yanlış girinti vardı. Sadece bunu düzelttim.
Jochen Schwarze

Bunu düzeltmek için teşekkürler, ama komut dosyasını çalıştırırken bir Python hatası alıyorum.
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

Zaten benzer bir eklenti var gibi görünüyor ( bir dizi oluşturmak yerine sizin için yeni bir benzersiz kimlik alanı oluşturmasına rağmen ).

Bu, zaten benzersiz bir kimlik alanınız olduğunu varsayar (bunun sayısal olması gerekmez), bunun yerine basit bir sayısal kimlik ister (1,2,3 ..).

İşleme araç kutusunda, Komut Dosyaları> Araçlar> Komut Dosyalarını Çevrimiçi Alın ...

"Kurulu değil" i genişletin ve "EquivalentNumField" ı seçin. Tamam'ı tıklamadan önce onay kutusunu tıklamayı unutmayın. Bu beni yakaladı ... ;-)

resim açıklamasını buraya girin

Hızlı bir şekilde bulmak için, işleme arama çubuğuna "Equiv" yazın ve oradan çift tıklayabilmeniz gerekir.

resim açıklamasını buraya girin

İşte bir örnek. Bu ormanda benzersiz bir alan (osm_id) vardı ancak eklenti bunun yerine basit sayısal değerlere sahip bir NUM_FIELD ekledi

resim açıklamasını buraya girin


Steve, bu yararlı bir senaryo ama farklı bir şey arıyorum.
eclipsed_by_the_moon

@eclipsed_by_the_moon bu cevap nasıl aradığınız değil? Benzersiz bir tanımlayıcı sütununa ihtiyaç duyma sorununuzu nihayetinde çözüyor gibi görünüyor.
kttii
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.