Incluindo variável na cláusula where de arcpy.Select_analysis ()?

21

Estou tentando fazer um loop através de um shapefile, selecionando cada recurso por vez e copiando-o para um shapefile temporário para ser incluído em uma análise de união. Estou usando um cursor para encontrar o nome do ID de cada recurso que estou definindo como um 'Nome' variável. Sempre que tento usar essa variável como parte da cláusula where no arcpy.Select_analysis, recebo um erro:

ExecuteError: ERRO 999999: Erro ao executar a função. Uma instrução SQL inválida foi usada. Uma instrução SQL inválida foi usada. Falha ao executar (Selecionar).

O código que estou usando é:

Name = 101
where = "\'\"StudyID\" = \\'"+str(Name)+"\\'\'"
arcpy.Select_analysis("C:\\input.shp", "C:\\output.shp", where)

Se eu digitar sem usar as variáveis:

arcpy.Select_analysis("C:\\input.shp", "C:\\output.shp", '"StudyID" = \'101\'')

Funciona bem

O que eu preciso fazer para ajustar a variável na instrução sql?

Flo Harrison
fonte

Respostas:

14

Outra maneira, talvez mais simples, é:

where = '"StudyID" = ' + "'%s'" %Name
Marcin
fonte
2
"Ao usar o ArcGIS 10 (ou, presumivelmente, mais tarde), os nomes dos campos não precisam ser citados" Isso está incorreto; os delimitadores de campo devem ser especificados de acordo com as regras de sintaxe do DBMS subjacente. Veja minha resposta.
blah238
O comentário acima foi uma resposta a uma edição anônima que revirei para verificar se a resposta está correta.
blah238
Isso não é uma vulnerabilidade de injeção SQL se Namevier da entrada do usuário?
Jpmc26
22

Uma coisa que facilita muito a escrita das cláusulas WHERE é usar o método AddFieldDelimiters função, que adiciona automaticamente os delimitadores corretos específicos do DBMS para identificadores de campo, como aspas duplas para FGDB e colchetes para PGDB.

A outra coisa que você deve considerar é se o valor é um número, sequência ou outro tipo de dados. Especificamente, as seqüências de caracteres são agrupadas em aspas simples, enquanto os números não. Você pode verificar o tipo de campo e adicionar aspas simples, se for um campo de sequência.

Por exemplo:

import arcpy

def buildWhereClause(table, field, value):
    """Constructs a SQL WHERE clause to select rows having the specified value
    within a given field and table."""

    # Add DBMS-specific field delimiters
    fieldDelimited = arcpy.AddFieldDelimiters(table, field)

    # Determine field type
    fieldType = arcpy.ListFields(table, field)[0].type

    # Add single-quotes for string field values
    if str(fieldType) == 'String':
        value = "'%s'" % value

    # Format WHERE clause
    whereClause = "%s = %s" % (fieldDelimited, value)
    return whereClause

if __name__ == "__main__":
    inputfc = r"C:\input.shp"
    outputfc = r"C:\output.shp"
    fieldname = "StudyID"
    fieldvalue = 101
    whereclause = buildWhereClause(inputfc, fieldname, fieldvalue)
    arcpy.Select_analysis(inputfc, outputfc, whereclause)

Consulte também a função nesta resposta para obter uma versão com vários valores da função acima.

blah238
fonte
2
Boa ideia. Eu adicionei esta função para meus funções auxiliares arcpy módulo de modo que é definido como arcpy.buildWhereClause
blord-castillo
3

Tente o seguinte:

Name = 1
study = "StudyID"

where = '"' + study + '" = ' + "'" + str(Name) + "'"
Roy
fonte
0

Eu gosto de usar aspas triplas. Eu acho que eles são os mais fáceis de ler. Por exemplo,

name = 101
where = """ "StudyID" = '%s' """ % name
arcpy.Select_analysis("C:\\input.shp", "C:\\output.shp", where)

Dependendo do type(name)que você pode ou não pode precisar da 'volta %s. Para números, você precisa do 'texto, mas não do texto.

gisdude
fonte
0

Para mim, esta solução funciona melhor, pois posso substituir uma variável pelo campo de interesse e pelos critérios de valor.

field = "Sport"
value = "Basketball"
where = """"{}" = '{}'""".format(field,value)
dwiz
fonte