如何从Bash脚本正确为MySQL赋值NULL值
问题描述
我有一个用于更新MySQL数据库的Bash脚本,通过if语句决定写入数据库的内容,但混淆了NULL值与字符串"NULL"。代码如下:
db_host="localhost" db_user="user" db_pass="pass" db_name="dbname" MyCmd="mysql -N -h $db_host -u $db_user -p$db_pass -D $db_name" if [[ $LastCh > 1516980000 ]]; then NewCh="$(date -d @$LastCh +"%Y-%m-%d %H:%M:%S")" elif [ -n "$NewCh" ]; then NewCh=$($MyCmd -e "SELECT MAX(LastChange) FROM Status WHERE IDN=$idn AND LastChange>0") # NewCh=$($MyCmd -e "SELECT MAX(LastChange) FROM Status WHERE IDN=$idn AND LastChange IS NOT NULL") else NewCh=NULL fi StatSQL="IDN, Name, LastIP, Activesince, LastChange" $MyCmd -e "INSERT INTO Status ($StatSQL) VALUES ('$idn', '$name', '$ip', '$activesince', '$NewCh')"
当脚本能获取到LastChange值时就直接写入数据库,否则需要从IDN字段的MAX(LastChange)取值,但如果存在至少一个NULL值,MAX结果会显示为NULL。我怀疑是有时赋值的NULL实际是字符串"NULL"导致WHERE子句失效,添加的AND LastChange IS NOT NULL条件无效,但LastChange>0有效但并非所有场景适用。
问题:
- 如何修改NewCh变量使其能传递NULL值?
- 如何区分数据库中的字段是NULL值还是字符串"NULL"?
解决方案
1. 让NewCh传递真正的MySQL NULL值
核心问题在于:当你给NewCh赋值NULL时,插入SQL里会被包裹成'NULL',MySQL会把它当作字符串而非空值。可以通过两种方式解决:
方法一:插入时判断处理
修改最后的INSERT逻辑,根据NewCh的值决定是否加引号:
StatSQL="IDN, Name, LastIP, Activesince, LastChange" if [ "$NewCh" = "NULL" ]; then # 插入真正的NULL,不加引号 $MyCmd -e "INSERT INTO Status ($StatSQL) VALUES ('$idn', '$name', '$ip', '$activesince', NULL)" else # 插入字符串值,保留引号 $MyCmd -e "INSERT INTO Status ($StatSQL) VALUES ('$idn', '$name', '$ip', '$activesince', '$NewCh')" fi
方法二:提前标记并替换
给NewCh设置空字符串作为NULL标记,再在生成SQL时替换成真实的NULL:
# 修改else分支,用空字符串标记NULL else NewCh="" fi # 构建SQL时处理空值 if [ -z "$NewCh" ]; then ch_value="NULL" else ch_value="'$NewCh'" fi $MyCmd -e "INSERT INTO Status ($StatSQL) VALUES ('$idn', '$name', '$ip', '$activesince', $ch_value)"
另外补充:当从数据库查询MAX(LastChange)时,如果结果是NULL,mysql -N会返回空行,此时NewCh会被赋值为空字符串,需要在elif分支后补充判断:
elif [ -n "$NewCh" ]; then NewCh=$($MyCmd -e "SELECT MAX(LastChange) FROM Status WHERE IDN=$idn AND LastChange IS NOT NULL") # 如果查询结果为空(即无有效非NULL值),设置为NULL标记 if [ -z "$NewCh" ]; then NewCh="NULL" fi
2. 区分数据库中的NULL和字符串"NULL"
MySQL里NULL是缺失的空值,字符串"NULL"是实际存储的文本,两者判断方式完全不同:
- 判断字段是否为NULL值:用
LastChange IS NULL或LastChange IS NOT NULL - 判断字段是否为字符串"NULL":用
LastChange = 'NULL'或LastChange != 'NULL'
你之前的AND LastChange IS NOT NULL条件无效,是因为表中存的是字符串"NULL"而非真正的NULL值;而LastChange>0有效,是因为MySQL会把字符串"NULL"转成数字0,0不满足>0的条件。如果要同时过滤两种无效值,可以用:
SELECT MAX(LastChange) FROM Status WHERE IDN=$idn AND LastChange IS NOT NULL AND LastChange != 'NULL'
内容的提问来源于stack exchange,提问作者DenisZ
相关产品推荐
相关产品推荐

