파이썬 sqlite3 테이블 이름 검색 질문
조회수 887회
db를 다를줄몰라서 json 형식으로 만들었다가 답변해주시는 분들이 db를 만들라고 추천해주셔서
db를 공부하면서 소스를 짜고 있는데요 일단 디비 저장하는것까지는 성공했습니다
크롤링하면서 데이터를 얻은 비제이 1명당 "db_아이디" 이름을 가진 테이블을 1개씩 만들어주고 있습니다 (현재 테이블 3천개정도)
테이블은 [고유번호,id,닉네임,날짜,제목,길이,링크,조회수] 이렇게 이루어져있구요
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, parsemode
from telegram.ext import Updater, MessageHandler, Filters, CommandHandler, CallbackQueryHandler
import time
from functools import partial
import logging
import sqlite3
import sys
formatter = logging.Formatter('[%(levelname)s] %(asctime)s > %(message)s')
file_handler = logging.FileHandler('./telegram_bot_db.log',encoding='utf-8')
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
logger = logging.getLogger("logger")
logger.setLevel(logging.DEBUG)
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
my_token = '#봇 토큰'
sys.setrecursionlimit(10000) #오류나서 검색해보고 추가함
conn = sqlite3.connect('af.db') # db연결
cur = conn.cursor()
print('start bot')
def search(bot, update): # 봇에 bjid를 입력하면
bjid = update.message.text # bjid =봇에 검색한 bjid
l=[]
bjid = bjid.lower() #첫글자가 자동 대문자 되는 사람들이 있어서 소문자로 변환
chat_id = update.message.chat_id # chat_id =봇을 사용한 사람의 텔레그램id
dbid = 'db_'+ bjid # bj아이디가 숫자로 시작하는경우 에러가 발생해서 테이블생성시 아이디앞에 db_붙임
cur.execute('select name from sqlite_master where type="table" and name="{}"'.format(dbid))
# 테이블 이름이 dbid 인것 선택
aa = cur.fetchall() # 검색한 bjid 이름을 가진 테이블이 있으면 테이블 이름있는 리스트 주고 없으면 [] 리턴
# bjid당 1개의 테이블만 있어서 fetchall,one 아무거나써도 하나만 반환
print(aa) # 여기서 부터가 문제 print한 값이 아무것도 안나옴
# if aa != '': #print 결과가 안나오니 아래는 당연히 안되서 주석처리
# update.message.reply_text('테이블 있음')
# else:
# update.message.reply_text('테이블 없음')
def get_message(bot, update) :
update.message.reply_text(time.time())
#print(update.message)
update.message.reply_text(update.message.text)
def help_command(bot, update) :
update.message.reply_text("문의")
def start(bot, update):
update.message.reply_text("시작")
updater = Updater(my_token)
message_handler = MessageHandler(Filters.text, search)
updater.dispatcher.add_handler(message_handler)
updater.dispatcher.add_handler(CommandHandler('start', start))
help_handler = CommandHandler('help', help_command)
updater.dispatcher.add_handler(help_handler)
updater.dispatcher.add_handler(CommandHandler('search', partial(search, offset=0)))
updater.start_polling(timeout=3, clean=True)
updater.idle()
아래 부분의 소스를 def search(bot, update): 함수안이 아닌 밖에서 실행하면 aa 값이 table이 있으면 테이블 이름을 print하고 없으면 [] 이 print 됩니다
dbid = 'db_'+ bjid
cur.execute('select name from sqlite_master where type="table" and name="{}"'.format(dbid))
aa = cur.fetchall()
print(aa)
텔레그램 봇에 bjid를 입력하면 db에 검색한후 그이름을 가진 테이블이 있으면 그 값들을 주려고하는데요 (비제이의 데이터를 얻었을때 테이블을 생성하므로 테이블 조회해서 있으면 해당 비제이의 데이터가 있음)
함수 안에서 작동을안하다가 함수밖에서 잘 작동을하니;; 어디가 잘못되었는지를 모르겠습니다
1 답변
-
일단 원인만 알려드리자면 참조 오류인데요.
def search(bot, update): bjid = update.message.text l=[] bjid = bjid.lower() chat_id = update.message.chat_id dbid = 'db_'+ bjid cur.execute(어쩌구 저쩌구)
이 소스를 잘 보시면,
search()
라는 메소드 안에서,cur
는 제7행에 갑자기 툭 튀어나옵니다. 이게 무엇을 가리키는지 파이썬이 알 도리가 없어서 에러가 나는 것이지요. "함수" 밖에서야 보시다시피cur
이 있으니 그걸 참조할 수 있는 거구요.
하지만 아무리 읽어봐도 이건 진짜 문제가 아닙니다. 윗분 댓글에도 나와 있지만 bj 한명한명에게 테이블이 있다는 것부터가 심각하게 문제입니다. 대부분의 경우 테이블의 '이름'을 '검색'해야 할 일은 없어요. 지금 현재의 그 설계는, 덜 긴밀한 관계를 가진 방대한 데이터를 축적하며 앞으로도 질문자님이 만들고 싶은 것을 끊임없이 가로막고 귀찮게 방해할 겁니다.
CREATE TABLE bj( bjid INTEGER PRIMARY KEY, bjname TEXT, /* 더 있겠지만 생략 */ ); CREATE TABLE bjclip( clipid INTEGER, cliptitle TEXT, clipbj INTEGER, /* 더 있겠지만 중간 생략하고 */ FOREIGN KEY(clipbj) REFERENCES bj(bjid) /* 중요 */ );
테이블 자료 구조가 저렇게만 되어 있다면, 거기서부터는 얘기가 훨씬 쉽습니다.
/* 사용자가 BJ 이름을 입력하면 그 BJ가 찍은 영상들을 그 BJ 이름과 함께 보여주기 */ SELECT * FROM bjclip JOIN bj ON bj.bjid = bjclip.clipbj WHERE bj.bjname LIKE '%사용자입력%'; /* 사용자가 영상 제목으로 검색했을 때 그 제목의 영상을 올린 BJ 들을 알려주기 */ SELECT * FROM bj WHERE bjid IN ( SELECT clipbj FROM bjclip WHERE cliptitle LIKE '%사용자입력%' );
위 쿼리들은 항상 '결과셋'이 됩니다. 그 결과셋의 크기는 0일 수도 있고 1 이상일 수도 있습니다. 파이썬은 이 결과셋을 그냥 for 돌면서 뿌려주면 됩니다. "앗 님이 검색하신 이름을 가진 BJ는 0명인데요?"를 알려주기 위해 커서를 획득하고 재귀횟수 한계를 지정하고 익셉션 처리를 붙이는 난리부르스를 추실 필요가 없는 겁니다.
지금이라도 데이터 구조 설계를 변경하시기를 강력히 권고 드립니다. 만들어져 있는 테이블들을 모두 하나의 테이블로 합치시고, BJ 정보만 모은 테이블을 따로 만들어서 서로 관계를 지어 주세요. 그게 빠른 길입니다.
댓글 입력