sourcecode

sqlite 쿼리에서 딕트를 가져오려면 어떻게 해야 합니까?

copyscript 2023. 6. 8. 22:26
반응형

sqlite 쿼리에서 딕트를 가져오려면 어떻게 해야 합니까?

db = sqlite.connect("test.sqlite")
res = db.execute("select * from table")

반복을 사용하여 행에 대응하는 코어 목록을 가져옵니다.

for row in res:
    print row

열 이름을 알 수 있습니다.

col_name_list = [tuple[0] for tuple in res.description]

하지만 목록 대신 사전을 얻을 수 있는 기능이나 설정이 있습니까?

{'col1': 'value', 'col2': 'value'}

아니면 제가 직접 해야 하나요?

문서의 예와 같이 row_factory를 사용할 수 있습니다.

import sqlite3

def dict_factory(cursor, row):
    d = {}
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d

con = sqlite3.connect(":memory:")
con.row_factory = dict_factory
cur = con.cursor()
cur.execute("select 1 as a")
print cur.fetchone()["a"]

또는 문서에서 다음 예제 직후에 제공되는 조언을 따릅니다.

튜플을 반환하는 것만으로는 충분하지 않고 열에 대한 이름 기반 액세스를 원한다면 row_factory를 최적화된 sqlite3로 설정하는 것을 고려해야 합니다.행 유형.Row는 메모리 오버헤드가 거의 없는 열에 대한 인덱스 기반 액세스와 대소문자를 구분하지 않는 이름 기반 액세스를 모두 제공합니다.사용자 정의 사전 기반 접근 방식이나 db_row 기반 솔루션보다 더 나을 수 있습니다.

두 번째 솔루션의 코드는 다음과 같습니다.

con = sqlite3.connect(…)
con.row_factory = sqlite3.Row   #   add this row
cursor = con.cursor()

Adam Schmideg와 Alex Marteli의 답변 모두에 부분적으로 그 답이 언급되어 있음에도 불구하고 저는 이 질문에 답한다고 생각했습니다.저와 같은 질문을 하는 다른 사람들이 쉽게 답을 찾기 위해서입니다.

conn = sqlite3.connect(":memory:")

#This is the important part, here we are setting row_factory property of
#connection object to sqlite3.Row(sqlite3.Row is an implementation of
#row_factory)
conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute('select * from stocks')

result = c.fetchall()
#returns a list of dictionaries, each item in list(each dictionary)
#represents a row of the table

sqlite3를 사용하기도 합니다.행 클래스 - 다음 형식의 문자열 형식을 사용할 수 없습니다.

print "%(id)i - %(name)s: %(value)s" % row

이를 극복하기 위해 저는 줄을 잡고 사전으로 변환하는 도우미 기능을 사용합니다.사전 개체가 Row 개체보다 선호되는 경우에만 사용합니다(예: Row 개체가 사전 API를 기본적으로 지원하지 않는 문자열 형식과 같은 경우).그러나 행 개체는 항상 사용합니다.

def dict_from_row(row):
    return dict(zip(row.keys(), row))       

SQLite에 연결한 후:con = sqlite3.connect(.....)실행하기만 하면 됩니다.

con.row_factory = sqlite3.Row

Voila!

PEP 249에서:

Question: 

   How can I construct a dictionary out of the tuples returned by
   .fetch*():

Answer:

   There are several existing tools available which provide
   helpers for this task. Most of them use the approach of using
   the column names defined in the cursor attribute .description
   as basis for the keys in the row dictionary.

   Note that the reason for not extending the DB API specification
   to also support dictionary return values for the .fetch*()
   methods is that this approach has several drawbacks:

   * Some databases don't support case-sensitive column names or
     auto-convert them to all lowercase or all uppercase
     characters.

   * Columns in the result set which are generated by the query
     (e.g.  using SQL functions) don't map to table column names
     and databases usually generate names for these columns in a
     very database specific way.

   As a result, accessing the columns through dictionary keys
   varies between databases and makes writing portable code
   impossible.

네, 직접 하세요.

@gandalf의 대답에서 언급했듯이, 사람은 다음을 사용해야 합니다.conn.row_factory = sqlite3.Row하지만 결과는 직접적인 사전이 아닙니다.다음에 "캐스트"를 추가해야 합니다.dict마지막 루프에서:

import sqlite3
conn = sqlite3.connect(":memory:")
conn.execute('create table t (a text, b text, c text)')
conn.execute('insert into t values ("aaa", "bbb", "ccc")')
conn.execute('insert into t values ("AAA", "BBB", "CCC")')
conn.row_factory = sqlite3.Row
c = conn.cursor()
c.execute('select * from t')
for r in c.fetchall():
    print(dict(r))

# {'a': 'aaa', 'b': 'bbb', 'c': 'ccc'}
# {'a': 'AAA', 'b': 'BBB', 'c': 'CCC'}

단축 버전:

db.row_factory = lambda c, r: dict([(col[0], r[idx]) for idx, col in enumerate(c.description)])

내 테스트에서 가장 빠른 테스트:

conn.row_factory = lambda c, r: dict(zip([col[0] for col in c.description], r))
c = conn.cursor()

%timeit c.execute('SELECT * FROM table').fetchall()
19.8 µs ± 1.05 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

vs:

conn.row_factory = lambda c, r: dict([(col[0], r[idx]) for idx, col in enumerate(c.description)])
c = conn.cursor()

%timeit c.execute('SELECT * FROM table').fetchall()
19.4 µs ± 75.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

당신이 결정하세요 :)

앞서 언급한 솔루션과 유사하지만 가장 컴팩트한 솔루션:

db.row_factory = lambda C, R: { c[0]: R[i] for i, c in enumerate(C.description) }

쿼리 결과 가져오기

output_obj = con.execute(query)
results = output_obj.fetchall()

옵션 1) Zip이 포함된 명시적 루프

for row in results:
    col_names = [tup[0] for tup in output_obj.description]
    row_values = [i for i in row]
    row_as_dict = dict(zip(col_names,row_values))

옵션 2) Dict Comp로 루프 속도 향상

for row in results:
    row_as_dict = {output_obj.description[i][0]:row[i] for i in range(len(row))}

저는 당신이 올바른 방향으로 가고 있었다고 생각합니다.이 작업을 매우 단순하게 수행하고 수행하려는 작업을 완료해 보겠습니다.

import sqlite3
db = sqlite3.connect("test.sqlite3")
cur = db.cursor()
res = cur.execute("select * from table").fetchall()
data = dict(zip([c[0] for c in cur.description], res[0]))

print(data)

단점은 테이블이 매우 크면 기억력 소모량에 살인이 된다는 것입니다.그러나 텍스트 및 숫자 열의 수천 행을 처리하는 사소한 응용 프로그램의 경우 이 간단한 접근 방식으로 충분합니다.

심각한 문제의 경우, 다른 많은 답변에서 제안한 대로 열 공장을 조사해야 합니다.

또는 sqlite3를 변환할 수 있습니다.다음과 같이 사전 행으로 이동합니다.이렇게 하면 각 행에 대한 목록이 있는 사전이 제공됩니다.

    def from_sqlite_Row_to_dict(list_with_rows):
    ''' Turn a list with sqlite3.Row objects into a dictionary'''
    d ={} # the dictionary to be filled with the row data and to be returned

    for i, row in enumerate(list_with_rows): # iterate throw the sqlite3.Row objects            
        l = [] # for each Row use a separate list
        for col in range(0, len(row)): # copy over the row date (ie. column data) to a list
            l.append(row[col])
        d[i] = l # add the list to the dictionary   
    return d

세 줄만 사용하는 일반적인 대안

def select_column_and_value(db, sql, parameters=()):
    execute = db.execute(sql, parameters)
    fetch = execute.fetchone()
    return {k[0]: v for k, v in list(zip(execute.description, fetch))}

con = sqlite3.connect('/mydatabase.db')
c = con.cursor()
print(select_column_and_value(c, 'SELECT * FROM things WHERE id=?', (id,)))

그러나 쿼리에서 아무것도 반환하지 않으면 오류가 발생합니다.이 경우에는...

def select_column_and_value(self, sql, parameters=()):
    execute = self.execute(sql, parameters)
    fetch = execute.fetchone()

    if fetch is None:
        return {k[0]: None for k in execute.description}

    return {k[0]: v for k, v in list(zip(execute.description, fetch))}

또는

def select_column_and_value(self, sql, parameters=()):
    execute = self.execute(sql, parameters)
    fetch = execute.fetchone()

    if fetch is None:
        return {}

    return {k[0]: v for k, v in list(zip(execute.description, fetch))}
import sqlite3

db = sqlite3.connect('mydatabase.db')
cursor = db.execute('SELECT * FROM students ORDER BY CREATE_AT')
studentList = cursor.fetchall()

columnNames = list(map(lambda x: x[0], cursor.description)) #students table column names list
studentsAssoc = {} #Assoc format is dictionary similarly


#THIS IS ASSOC PROCESS
for lineNumber, student in enumerate(studentList):
    studentsAssoc[lineNumber] = {}

    for columnNumber, value in enumerate(student):
        studentsAssoc[lineNumber][columnNames[columnNumber]] = value


print(studentsAssoc)

결과는 확실히 사실이지만, 저는 가장 좋은 것은 모릅니다.

python의 사전은 해당 요소에 대한 임의 액세스를 제공합니다.따라서 "이름"이 있는 사전은 한 편으로는 유용할 수 있지만(예: 필드 이름이 무엇인지), 원하지 않을 수도 있는 필드의 "순서를 취소"합니다.

가장 좋은 방법은 이름을 별도의 목록에 넣은 다음 필요한 경우 직접 결과와 결합하는 것입니다.

try:
         mycursor = self.memconn.cursor()
         mycursor.execute('''SELECT * FROM maintbl;''')
         #first get the names, because they will be lost after retrieval of rows
         names = list(map(lambda x: x[0], mycursor.description))
         manyrows = mycursor.fetchall()

         return manyrows, names

또한 모든 접근 방식에서 이름은 데이터베이스의 이름이 아니라 쿼리에서 제공한 이름입니다.예외는 다음과 같습니다.SELECT * FROM

사전을 이라면, "" "" "" ""를 하세요.conn.row_factory = sqlite3.Row(다른 답변에 명시되어 있음).

def getUsers(self,assoc=False):
        result = self.cursor.execute("SELECT * FROM users").fetchall()
        result_len = len(result)
        if(result_len == False): return
        if(assoc != True):
            return result
        else:
            result_formated = []
            columns = [column[0] for column in self.cursor.description]
            for row in result:
                row_dict = {}
                i = 0
                # print(result_len)
                while(i <= result_len):
                    row_dict[columns[i]] = row[i]
                    i += 1
                result_formated.append(row_dict)
            return result_formated

저는 그냥 제 나쁜 코드를 여기에 두겠습니다.

언급URL : https://stackoverflow.com/questions/3300464/how-can-i-get-dict-from-sqlite-query

반응형