【问题标题】:Lambda (Python 3.6) PyMySql Query EXISTS query always returns 1Lambda (Python 3.6) PyMySql Query EXISTS 查询总是返回 1
【发布时间】:2018-04-23 19:27:39
【问题描述】:

我正在尝试在 Lambda (Python 3.6) 中获取 PyMySQL 查询以返回用户是否存在。我将我的 slack 用户 ID 传递到查询中。这就是我想在 MySQL 中检查的内容。我可以通过 MySQL 运行相同的查询并返回 0,但由于某种原因,每次我通过 lambda 调用此查询时,它都会告诉我用户存在(我的数据库为空)。我的查询功能是这样的:

def userExists(user):
    statement = f"SELECT EXISTS(SELECT 1 FROM slackDB.Assets WHERE userID LIKE '%{user}%')Assets"
    tempBool  = cursor.execute(statement, args=None) 
    conn.commit()
    return tempBool

这是我正在使用的完整代码:

################################
# Slack Lambda handler.
################################

import sys
import logging
import os
import pymysql
import urllib

# Grab data from the environment.
BOT_TOKEN   = os.environ["BOT_TOKEN"]
ASSET_TABLE = os.environ["ASSET_TABLE"]
REGION_NAME = os.getenv('REGION_NAME', 'us-east-2')

DB_NAME     = "admin"
DB_PASSWORD = "somepassword"
DB_DATABASE = "someDB"
RDS_HOST    = "myslackdb.somepseudourl.us-east-2.rds.amazonaws.com"
port        = 3306

logger = logging.getLogger()
logger.setLevel(logging.INFO)

try:
    conn = pymysql.connect(RDS_HOST, user=DB_NAME, passwd=DB_PASSWORD, db=DB_DATABASE, connect_timeout=5)
    cursor = conn.cursor()
except:
    logger.error("ERROR: Unexpected error: Could not connect to MySql instance.")
    sys.exit()

# Define the URL of the targeted Slack API resource.
SLACK_URL = "https://slack.com/api/chat.postMessage"

def userExists(user):
    statement = f"SELECT EXISTS(SELECT 1 FROM slackDB.Assets WHERE userID LIKE '%{user}%')Assets"
    tempBool  = cursor.execute(statement, args=None) 
    conn.commit()
    return tempBool

def addUser(user):
    statement = f"INSERT INTO `slackDB`.`Assets` (`userID`, `money`) VALUES ('{user}', '1000')"
    tempBool  = cursor.execute(statement, args=None) 
    conn.commit()
    return tempBool

def lambda_handler(data, context):
    # Slack challenge answer.
    if "challenge" in data:
        return data["challenge"]

    # Grab the Slack channel data.
    slack_event    = data['event']
    slack_userID   = slack_event["user"]
    slack_text     = slack_event["text"]
    channel_id     = slack_event["channel"]
    slack_reply    = ""

    # Ignore bot messages.
    if "bot_id" in slack_event:
        slack_reply = ""
    else:
        # Start data sift.
        if slack_text.startswith("!networth"):
            slack_reply = "Your networth is: "
        elif slack_text.startswith("!price"):
            command,asset = text.split()
            slack_reply = f"The price of a(n) {asset} is: "
        elif slack_text.startswith("!addme"):
            if userExists(slack_userID):
                slack_reply = f"User {slack_userID} already exists"
            else:
                slack_reply = f"Adding user {slack_userID}"
                addUser(slack_userID)

        # We need to send back three pieces of information:
        data = urllib.parse.urlencode(
            (
                ("token", BOT_TOKEN),
                ("channel", channel_id),
                ("text", slack_reply)
            )
        )
        data = data.encode("ascii")

        # Construct the HTTP request that will be sent to the Slack API.
        request = urllib.request.Request(
            SLACK_URL, 
            data=data, 
            method="POST"
        )
        # Add a header mentioning that the text is URL-encoded.
        request.add_header(
            "Content-Type", 
            "application/x-www-form-urlencoded"
        )

        # Fire off the request!
        urllib.request.urlopen(request).read()

    # Everything went fine.
    return "200 OK"

我在 slack 中输入“!addme”,它总是告诉我用户存在。我已打印出我的查询语句,它正在正确输入我的 slack ID。我检查了我的桌子,它完全是空的。我在 MySQL 中运行了查询,它返回一个 0。

有人有什么想法吗?我只是在简单地谈论这个吗?非常感谢任何帮助或提示。

谢谢,

【问题讨论】:

    标签: mysql python-3.x aws-lambda slack-api


    【解决方案1】:

    我没有从光标处看到fetch。只是execute。

    execute 的返回值是受影响的行数。对于有意义的 DML 操作 (INSERT/UPDATE/DELETE)。但我不会依赖 SELECT 的受影响行数。

    在这种情况下,SELECT EXISTS 查询要么返回一行,要么抛出一个错误。但是查询返回一行的事实并没有告诉我们关于Assets 列的值的任何信息。

    从查询来看,我们想要获取一行,然后确定Assets 列是否包含 0 或 1(或 NULL)。

    查询执行后,尝试cur.fetchone检索行。


    我们还可以执行一个更简单的查询,然后使用 fetch 来确定是否返回了一行。

    【讨论】:

    • cursor.execute(statement, args=None) tempBool = cursor.fetchone() 刚刚尝试过,它没有返回任何错误(耶!),但它总是每次都返回 1。有什么想法吗?
    • 所以 fetch 返回了一行。这是我们所期望的。 SELECT EXISTS 将返回一行。重要的是行的内容......是Assets 列等于1(至少找到一行),还是等于0(没有找到行。)这是我们可以简化事情的地方...... . 抛弃 SELECT EXISTS 包装器,只运行返回行(如果找到)或不返回行(当未找到行)的查询。我们可以添加 LIMIT 1 子句以避免返回更多除了一行,我们只关心是否返回一行。然后我们就可以使用来自fetchone 的返回。
    • 如果我们要坚持使用SELECT EXISTS 查询,我们需要实际获取行,并检查返回的行。我们需要获取Assets 列的值。
    • 谢谢!我将尝试放弃 SELECT EXISTS 并添加 LIMIT 1。感谢您的解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2020-11-06
    相关资源
    最近更新 更多