Để "tự động hóa" quá trình nhập .sql
tệp được tạo , đồng thời tránh tất cả các bẫy có thể bị ẩn khi cố chuyển tệp qua stdin
và stdout
, chỉ cần báo cho MySQL thực hiện .sql
tệp được tạo bằng cách sử dụngSOURCE
lệnh trong MySQL.
Cú pháp trong câu trả lời ngắn, nhưng xuất sắc , từ Kshitij Sood , đưa ra điểm khởi đầu tốt nhất. Nói tóm lại, sửa đổi lệnh của OP theo cú pháp của Kshitij Sood và thay thế các lệnh trong đó bằng SOURCE
lệnh:
#!/bin/bash
mysql -u$user -p$password $dbname -Bse "SOURCE ds_fbids.sql
SOURCE ds_fbidx.sql"
Nếu tên cơ sở dữ liệu được bao gồm trong tạo .sql
tệp , nó có thể được loại bỏ khỏi lệnh.
Giả định ở đây là tệp được tạo có giá trị như một .sql
tệp của chính nó. Bằng cách không có tệp được chuyển hướng, đường ống hoặc theo bất kỳ cách nào khác được xử lý bởi trình bao, không có vấn đề gì về việc cần phải thoát bất kỳ ký tự nào trong đầu ra được tạo vì trình bao. Các quy tắc liên quan đến những gì cần phải thoát trong một .sql
tập tin, tất nhiên, vẫn được áp dụng.
Làm thế nào để giải quyết các vấn đề bảo mật xung quanh mật khẩu trên dòng lệnh, hoặc trong một my.cnf
tệp, v.v., đã được giải quyết tốt trong các câu trả lời khác, với một số gợi ý tuyệt vời. Câu trả lời yêu thích của tôi , từ Daniel , bao gồm điều đó, bao gồm cả cách xử lý vấn đề khi giải quyết cron
công việc, hoặc bất cứ điều gì khác.
Để giải quyết một nhận xét (câu hỏi?) Về câu trả lời ngắn gọn mà tôi đã đề cập: Không, nó không thể được sử dụng với cú pháp HEREDOC, vì lệnh shell đó được đưa ra. HEREDOC có thể được sử dụng trong cú pháp phiên bản chuyển hướng , (không có -Bse
tùy chọn), vì chuyển hướng I / O là những gì HEREDOC được xây dựng xung quanh. Nếu bạn cần chức năng của HEREDOC, sẽ tốt hơn nếu sử dụng nó trong việc tạo .sql
tệp, ngay cả khi đó là tạm thời và sử dụng tệp đó làm "lệnh" để thực thi với dòng lô MySQL.
#!/bin/bash
cat >temp.sql <<SQL_STATEMENTS
...
SELECT \`column_name\` FROM \`table_name\` WHERE \`column_name\`='$shell_variable';
...
SQL_STATEMENTS
mysql -u $user -p$password $db_name -Be "SOURCE temp.sql"
rm -f temp.sql
Hãy nhớ rằng vì mở rộng shell, bạn có thể sử dụng các biến shell và môi trường trong HEREDOC. Mặt trái là bạn phải thoát khỏi mọi backtick. MySQL sử dụng chúng làm các dấu phân cách cho các định danh nhưng shell, lấy chuỗi đầu tiên, sử dụng chúng làm các dấu phân cách lệnh thực thi. Bỏ lỡ lối thoát trên một backtick duy nhất của các lệnh MySQL và toàn bộ sự việc phát nổ với lỗi. Toàn bộ vấn đề có thể được giải quyết bằng cách sử dụng Giới hạn được trích dẫn cho HEREDOC:
#!/bin/bash
cat >temp.sql <<'SQL_STATEMENTS'
...
SELECT `column_name` FROM `table_name` WHERE `column_name`='constant_value';
...
SQL_STATEMENTS
mysql -u $user -p$password $db_name -Be "SOURCE temp.sql"
rm -f temp.sql
Loại bỏ mở rộng shell theo cách đó giúp loại bỏ sự cần thiết phải thoát khỏi backticks và các ký tự đặc biệt khác của shell. Nó cũng loại bỏ khả năng sử dụng các biến shell và môi trường bên trong nó. Điều đó khá nhiều loại bỏ các lợi ích của việc sử dụng HEREDOC trong tập lệnh shell để bắt đầu.
Tùy chọn khác là sử dụng các chuỗi trích dẫn nhiều dòng được phép trong Bash với phiên bản cú pháp bó (với -Bse
). Tôi không biết các loại vỏ khác, vì vậy tôi không thể nói nếu chúng cũng hoạt động trong đó. Bạn sẽ cần phải sử dụng điều này để thực thi nhiều hơn một .sql
tệp bằng SOURCE
lệnh, vì điều đó không bị chấm dứt bởi một ;
lệnh MySQL khác và chỉ một tệp được phép trên mỗi dòng. Chuỗi nhiều dòng có thể được trích dẫn một hoặc hai lần, với các hiệu ứng bình thường đối với việc mở rộng hệ vỏ. Nó cũng có những cảnh báo tương tự như sử dụng cú pháp HEREDOC dành cho backticks, v.v.
Một giải pháp tiềm năng tốt hơn là sử dụng ngôn ngữ kịch bản, Perl, Python, v.v., để tạo .sql
tệp, như OP đã làm và SOURCE
tệp đó sử dụng cú pháp lệnh đơn giản ở trên cùng. Các ngôn ngữ kịch bản lệnh xử lý chuỗi tốt hơn nhiều so với trình bao, và hầu hết đều có các quy trình được xây dựng để xử lý trích dẫn và thoát cần thiết khi giao dịch với MySQL.