Linux Shell中动态SQL拼接核心是安全可控嵌入变量:须用${var}规范引用、禁用空格赋值;防注入需优先用数据库原生参数机制,次选printf %q转义或正则校验数字,执行时注意Shell展开与SQL解析协同。

在 Linux Shell 中实现动态 SQL 拼接,核心是把变量安全、可控地嵌入 SQL 字符串中,同时避免语法错误和 SQL 注入风险。关键不在于“拼得多快”,而在于“拼得稳、传得准、执行得干净”。
变量定义与基础拼接
Shell 变量赋值时等号两侧不能有空格,引用时加 $ 符号:
-
正确写法:
db_name="prod_db"; table_name="users"; sql="SELECT * FROM ${table_name} WHERE status='active'"; echo "$sql" -
错误写法:
db_name = "prod_db"(空格导致赋值失败)或echo $sql(未引号包裹,遇空格/特殊字符易截断)
推荐始终用 ${var} 而非 $var,尤其当变量后紧跟字母或下划线时(如 ${db_name}_backup),可避免歧义。
安全传参:防止 SQL 注入与格式错乱
直接拼接用户输入或外部参数极危险。应优先使用数据库客户端的原生参数机制,或做严格过滤:
- MySQL 支持
--defaults-file或-e+ 单引号包裹整个 SQL,但变量仍需 Shell 层预处理 - 更稳妥方式:用
printf %q对变量转义(适用于简单字符串):user_input="O'Reilly & Co."; safe_input=$(printf %q "$user_input"); sql="INSERT INTO logs(msg) VALUES ($safe_input)" - 对数字类参数,可用正则校验:
[[ "$id" =~ ^[0-9]+$ ]] && sql="DELETE FROM orders WHERE id=$id"
结合 SQL*Plus / MySQL CLI 执行动态语句
实际执行时,需兼顾 Shell 变量展开与 SQL 客户端解析逻辑:
-
MySQL 示例:
mysql -uadmin -p$PASSWD "$db_name" -e "UPDATE ${table_name} SET status='done' WHERE id=${task_id};" -
SQL*Plus 示例(Oracle):
先在 SQL 脚本中预留变量占位:UPDATE emp SET sal = &1 WHERE deptno = &2;
再用 Shell 调用:sqlplus -s /nolog CONNECT / AS SYSDBA<br>@update_emp.sql $new_sal $dept_no<br>EXIT;<br>EOF
- 注意:
-s(silent)关闭提示;set feedback off heading off pagesize 0等 SQL*Plus 设置可净化输出,便于后续 Shell 处理结果
进阶:用 Here Document 处理多行动态 SQL
适合结构复杂、含变量且需保持缩进的场景:
mysql -u root "$target_db" INSERT INTO reports (title, data_json, created_at)<br>VALUES ('$report_title', '$json_data', NOW());<br>UPDATE stats SET last_run=NOW() WHERE id=1;<br>SQL_END- 注意:Here Document 中若使用双引号界定符(如
),变量不会展开;若用 <code>(无引号),则变量正常展开 - 敏感内容(如密码、JSON)建议先存入临时变量并做
printf %q处理,再代入











