Uwzględniając zmienną w której klauzuli arcpy.Select_analysis ()?

21

Próbuję zapętlić plik kształtu, wybierając kolejno każdą funkcję i kopiując ją do tymczasowego pliku kształtu, aby uwzględnić ją w analizie związku. Używam kursora, aby znaleźć nazwę ID dla każdej funkcji, dla której ustawiam zmienną „Nazwę”. Ilekroć próbuję użyć tej zmiennej jako część klauzuli where w arcpy.Select_analysis, pojawia się błąd:

ExecuteError: ERROR 999999: Błąd wykonywania funkcji. Użyto niepoprawnej instrukcji SQL. Użyto niepoprawnej instrukcji SQL. Nie udało się wykonać (Wybierz).

Używam kodu:

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

Jeśli wpisuję to bez użycia zmiennych:

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

to działa dobrze

Co muszę zrobić, aby dopasować zmienną do instrukcji SQL?

Flo Harrison
źródło

Odpowiedzi:

14

Innym, może prostszym sposobem jest:

where = '"StudyID" = ' + "'%s'" %Name
Marcin
źródło
2
„Podczas korzystania z ArcGIS 10 (lub, prawdopodobnie, później), nazwy pól nie muszą być cytowane” Jest to niepoprawne; ograniczniki pól muszą być określone zgodnie z podstawowymi regułami składni DBMS. Zobacz moją odpowiedź.
blah238
Powyższy komentarz był odpowiedzią na anonimową edycję, którą wycofałem dla poprawności tej odpowiedzi.
blah238
Czy nie jest to luka w zabezpieczeniach polegająca na wstrzykiwaniu kodu SQL, jeśli Namepochodzi od danych wprowadzonych przez użytkownika?
jpmc26
22

Jedną z rzeczy, która znacznie ułatwia pisanie klauzul WHERE, jest użycie AddFieldDelimitersfunkcji, która automatycznie dodaje poprawne, specyficzne dla DBMS separatory dla identyfikatorów pól, takie jak podwójne cudzysłowy dla FGDB i nawiasy kwadratowe dla PGDB.

Inną rzeczą, którą musisz wziąć pod uwagę, jest to, czy wartość jest liczbą, łańcuchem lub innym typem danych. W szczególności ciągi są zawinięte w pojedyncze cudzysłowy, a liczby nie. Możesz sprawdzić typ pola i dodać pojedyncze cudzysłowy, jeśli jest to pole ciągu.

Na przykład:

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)

Zobacz także funkcję w tej odpowiedzi, aby uzyskać wielowartościową wersję powyższej funkcji.

blah238
źródło
2
Świetny pomysł. Dodałem tę funkcję do mojego modułu funkcji arcpy helper, więc jest ona zdefiniowana jako arcpy.buildWhereClause
blord-castillo
3

Spróbuj tego:

Name = 1
study = "StudyID"

where = '"' + study + '" = ' + "'" + str(Name) + "'"
Roy
źródło
0

Lubię używać potrójnych cytatów. Myślę, że są najłatwiejsze do odczytania. Na przykład,

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

W zależności od tego type(name)możesz potrzebować lub nie być w 'pobliżu %s. W przypadku liczb potrzebujesz znaku, 'ale nie tekstu.

gisdude
źródło
0

Dla mnie to rozwiązanie działa najlepiej, ponieważ mogę zastąpić zmienną zarówno polem zainteresowania, jak i kryterium wartości.

field = "Sport"
value = "Basketball"
where = """"{}" = '{}'""".format(field,value)
dwiz
źródło