導出為與 SQL Server 兼容的格式
我需要以可以導入 Microsoft SQL Server 數據庫的格式提供數據;但是,我沒有 Windows 或訪問 SQL Server 實例。
數據目前位於多個 CSV 電子表格中。我查看了
BULK INSERT
但發現他們對 CSV 的支持非常有限,例如無法辨識雙引號(文件:指定欄位和行終止符)。我已經讀過不支持邊緣情況,例如當欄位碰巧包含引號(因此需要轉義)時。是否有可以從 Linux/OSX 生成的更可靠的中間格式?例如 MySQL 轉儲、Excel、Sqlite、XML 等?
我還需要這個導入過程來創建表並且不需要編碼。導入的人是非技術人員。這將是一個一次性的過程。
- 目標系統是 SQL Server 2008,儘管我對不綁定到特定版本的解決方案非常感興趣。
- 單個 CSV 文件中要導入的數據約為 100MB。
- 有嵌入的欄位/行分隔符,當使用 Python csv 模組引用欄位時可以正常工作。
- 無需處理外鍵、索引、約束等。
- 編碼為 UTF-8。
- 來源是從目前儲存在 CSV 文件中的德國網頁中抓取的數據。如果這是一個可靠的向量,我可以輕鬆地將它從那裡導入 MySQL / Postgres。
我將無法測試導入,因為我無法直接訪問 SQL Server 數據庫,因此正在尋找更可靠的方法。例如 MySQL 轉儲、XLS、XML 等。
此請求存在一些問題:
- 目標系統是什麼版本的 SQL Server?
- 導入了多少數據?10k、10 Mb 還是更多?
- 有多少個 CSV 文件?
- 您已聲明需要處理雙引號,這意味著文本限定欄位和嵌入的文本限定符。是否還會有嵌入式欄位分隔符(即
,
)?這些通常不是問題,但是否還會嵌入行分隔符(即\r\n
或只是\n
)?這些是大多數 CSV 解析器的最大問題。- 在對 Scott 的回答發表評論時,您提出了以下問題:“雙引號就是一個例子,如果缺少這樣的基本功能——unicode、大小限制等,我預計還會有其他缺點。 ”。您能否更新問題以包括這些和任何其他缺失的要求?
- 在對問題的評論中,您問到 SSMS:“這會創建所需的表還是必須預定義? ”。創建表是此導入過程的要求嗎?如果是這樣,或者即使創建表是一個可選的好處,是否可以在問題中明確說明?
- 如果表不存在,關於外鍵、索引、預設約束、檢查約束等需要發生什麼?
- 正在使用什麼排序規則,或者至少 SQL Server 表需要什麼排序規則?是否計劃簡單地繼承您要導入的數據庫的目前預設排序規則?並且要清楚術語“排序規則”,因為根據您使用的系統,它的含義可能略有不同,我說的是:區域設置/LCID/文化/程式碼頁(如果適用)。它還有助於了解源是否對大小寫、重音等敏感或不敏感,或者是否正在使用二進制排序規則。
- >
是否有可以從 Linux/OSX 生成的更可靠的中間格式?例如 MySQL 轉儲、Excel、Sqlite、XML 等?
唯一真正可靠的格式是由 SQL Server生成的。XML 通常對於傳輸數據非常可靠(這是 XML 的本意),並且不存在分隔文件(即嵌入的文本限定符和分隔符)中固有的解析問題。但是,您仍然需要創建表,並且您需要編寫並測試將 XML 解析為結果集,以便可以將其插入表中。但是,(在下一項中繼續)… 10. 您在那條評論中對斯科特的回答說:
問題是我無法測試導入,因為我沒有直接訪問 MS SQL 數據庫的權限,所以我正在尋找更可靠的方法。
“可靠性”只能通過測試來確定。什麼應該起作用並不重要,任何事情都可能出錯。例如,許多人不知道 XML 通常使用 UTF-8 編碼,但 SQL Server 僅處理 XML 甚至 NVARCHAR 數據的 UTF-16(小端序)。看到這些數據是如何來自“Linux/OSX”的,我希望預設編碼是 UTF-8。
編碼問題和其他細微差別都應該(嗯,“大部分”)在測試中顯現出來,但你沒有辦法測試。因此,對於可靠的進口機制,很難得到一個非常可靠的答案。 11. 數據的來源是什麼?我假設它是問題中提到的Linux或OSX。但它是否專門來自 MySQL(因為還提到了“MySQL 轉儲”)?了解源是 MySQL 還是 PostgreSQL 或平面文件等將有助於確定哪些工具既可用又最適合此請求。 12. 然而,無論來源如何,請記住,目的地(即 Windows / SQL Server)最“舒適”地處理 UTF-16(小端序)編碼數據。因此,雖然 UTF-8 可能是基於 Linux/OSX 的系統的預設輸出類型,但如果可以選擇使用 UTF-16 Little Endian 進行輸出編碼,那麼一旦將腳本移至目的地系統。
**最後要考慮的一件事:**您提到“MySQL 轉儲”是一種潛在的“可靠格式”,這些轉儲包括 DDL (ie
CREATE TABLE
) 和 DML (ieINSERT
) 語句。如果您有能力編寫包含 DDL 語句(如有必要)和 DML 語句的腳本,那麼您不必擔心任何格式問題。只需將 CSV 數據轉換為INSERT
語句即可。剩下的唯一問題是無法測試腳本。但是,除了對象名稱和字元串文字使用哪種類型的引號或括號之外,真的很難出錯:INSERT INTO table (column1_name, column2_name, ...) VALUES (column1_val, column2_val, ...);
為了讓事情變得更容易:
- 將表名和列名括在方括號中:
[
和]
(例如[Customers]
),或雙引號:("
例如"Customers"
)- 將字元串、日期和 GUID 文字括在正常單引號/撇號中:
'
. (例如'some text'
)- 如果任何字元串文字用於 Unicode //
NVARCHAR
列XML
,請在這些文字前面加上大寫字母“N”:(N
例如N'some unicode text'
)- 確保任何日期/日期時間值都以兼容的方式格式化(有幾個選項,有些取決於 SQL Server 中的目前語言設置,但通常
YYYY-MM-DD HH:mm:ss.mmm
應該沒問題)- CHAR / VARCHAR 和 BINARY / VARBINARY 列的最大大小/長度為 8000。任何更大的都需要分別使用
VARCHAR(MAX)
和VARBINARY(MAX)
。- NCHAR / NVARCHAR 列(即 Unicode)的最大大小/長度為 4000。任何更大的都需要使用
NVARCHAR(MAX)
.由於問題中提到了 MySQL,即使是間接的,我認為使用mysqldump進行測試以查看它實際上可以達到多近也不會受到傷害。我使用了以下選項:
--flush-logs --compatible=mssql --no-create-db --no-tablespaces --order-by-primary --default-character-set=utf8 --flush-logs --skip-set-charset --hex-blob --result-file --skip-add-locks --skip-triggers --skip-comments --skip-disable-keys --compact --skip-extended-insert --skip-add-drop-table --quote-names
一些注意事項:
我用作
utf8
字元集,因為在此特定上下文中不允許使用 , 和其他一些utf16le
字元集 :-(ucs2
底部的兩個選項 -
--skip-add-drop-table
和--quote-names
- 可能不需要明確說明,因為它們可能暗示--compatible=mssql
至少您需要對輸出文件進行一些字元串替換,以調整 SQL Server 的語法。在下面的列表中,請密切注意“before”和“after”字元串之前和有時之後的空格,因為它們是防止匹配有效字元串部分所必需的。
- “int(11)”->“INT”
- “時間戳”->“日期時間”
- “文本”->“VARCHAR(MAX)”
- “blob”->“VARBINARY(MAX)”
- “ DEFAULT NULL” -> “ NULL”(“之前”或“之後”字元串的末尾沒有空格)
在進行了上面直接提到的 5 項調整之後,您仍然會遇到一些潛在問題:
- 上面的任何字元串替換是否意外匹配任何字元串列中的文本?
- 如果有任何
varchar
長度為 8001 或更大的列,則需要將這些長度轉換為字元串MAX
,以便生成的數據類型將VARCHAR(MAX)
代替VARCHAR(20000)
.- 如果您有任何 Unicode 數據,尤其是任何不適合目標數據庫預設排序規則的程式碼頁的字元,它將被轉換為問號 (
?
),除非您能找到一種方法來為這些字元串文字加上大寫前綴-N
。沿著這些相同的構想,CREATE TABLE
將需要針對任何 Unicode 列調整語句,以便它們是NCHAR
/NVARCHAR
而不是CHAR
/VARCHAR
。非 Unicode 列可以保留為CHAR
/VARCHAR
。- 我可能錯過的其他細微差別/差異。
PS為了完整起見,因為它涉及將數據從 MySQL 遷移到 SQL Server,Microsoft 確實有一個Migration Assistant,但據我所知,它需要從 SQL Server 到 MySQL 的連接,並且不適用於轉儲文件.
更新
新資訊(來自對此答案的評論):
來源是從目前儲存在 CSV 文件中的德國網頁中抓取的數據。如果這是一個可靠的向量,我可以輕鬆地將它從那裡導入 MySQL / Postgres。
所以這裡有一個想法。如果您可以將這些數據輸入到一個 RDBMS 中,那麼為什麼不可以呢?假設您要設置一個臨時 Windows VM 進行測試,您可以:
在 VM 上安裝SQL Server 2008 Express Edition(即免費)
創建一個數據庫來保存這些數據(如果你能從你的客戶那裡找出他們的數據庫使用的是什麼預設排序規則並為這個新數據庫使用相同的排序規則,這將使生活變得更容易!)
為此數據創建預期的架構(表等)
將此數據直接導入這些表
取一個
BACKUP
這個數據庫創建另一個數據庫作為您客戶的數據庫
編寫一個腳本,它將:
RESTORE
備份文件到具有新名稱(不是原始名稱)的新數據庫中將新數據庫中的表/數據複製到“客戶”數據庫中
DROP
新/數據遷移數據庫測試!
將備份文件和使用它的腳本提供給您的客戶端。
雖然這確實需要您編寫 T-SQL 腳本,但它不需要任何額外的軟體或安裝,並且數據已經在正確數據類型的列中並且不需要解析:-)。
PS 同樣,為了完整起見,我還將 SQL Server Data Tools (SSDT) 視為一種可能的解決方案,因為它可以將架構和數據導出到單個**.dacpac**文件中並將其導入到目標中。但是,這確實需要安裝 SSDT。但是,您不必編寫 T-SQL 腳本,因為 SSDT 會為您處理所有 SQL。