testMySQL)testMySQL| 問題 | 根因 | 影響 |
|---|---|---|
ntext/image 類型無法寫入 | ODBC 驅動/目標表類型不支援 | 大文本/二進制數據全軍覆沒 |
| 時間類型衝突 | 目標表設計用 INT 存 Unix 時間戳,源為 DATETIME | 導入報錯或數據錯誤 |
| 目標表類型自動映射不準 | DTS 類型推斷邏輯固化 | VARCHAR(8000) 變 TEXT、精度丟失等 |
| 無法控制批次/事務/錯誤重試 | 黑盒過程 | 大表失敗無法斷點續傳 |
**作者結論**:「此種方法我覺得不能提倡。」
ntext→VARCHAR(4000)、image→文件系統+路徑存庫、DATETIME→Unix Timestamp (INT)WHERE updated_at > last_sync 實現增量$cnx = odbc_connect('web', 'admin', '123456'); // SQL Server DSN
$cur = odbc_exec($cnx, 'SELECT * FROM user');
$conn = mysql_pconnect('localhost', 'root', '123456');
mysql_select_db('mydb', $conn);
while (odbc_fetch_row($cur)) {
$f1 = odbc_result($cur, 1); // id
$f2 = odbc_result($cur, 2); // name
$f3 = odbc_result($cur, 3); // username
$f4 = odbc_result($cur, 4); // password
$f5 = odbc_result($cur, 5); // recdate (DATETIME)
$f5 = timetoint($f5); // → Unix Timestamp INT
$sql = "INSERT INTO user (id,name,username,password,recdate)
VALUES ('$f1','$f2','$f3','$f4','$f5')";
mysql_query($sql, $conn);
}
function timetoint($str) {
list($date, $time) = explode(' ', $str);
list($y,$m,$d) = explode('-', $date);
list($h,$i,$s) = explode(':', $time);
return mktime($h,$i,$s,$m,$d,$y);
}
Set conn = Server.CreateObject("ADODB.Connection")
conn.Open "web", "admin", "123456" ' SQL Server DSN
' 關鍵:SQL 層面直接轉 Unix Timestamp,避免應用層循環轉換
sql = "SELECT ID, name, username, password,
DATEDIFF(s, '1970-01-01 00:00:00', recdate) - 8*3600 AS uts,
reid, filename, fileContentType, filevalue
FROM senddate"
Set rs = conn.Execute(sql)
Set conn1 = Server.CreateObject("ADODB.Connection")
conn1.Open "myoa", "root", "q1-d6=7?"
Do While Not rs.EOF
f1 = rs(0): f2 = rs(1): f3 = rs(2): f4 = rs(3): f5 = rs(4) ' uts 已是 INT
sql1 = "INSERT INTO user (ID,name,username,password,recdate) VALUES (" & f1 & ",'" & f2 & "','" & f3 & "','" & f4 & "'," & f5 & ")"
conn1.Execute sql1
rs.MoveNext
Loop
' ... 關閉連接清理
ntext/image 類型ntext → NVARCHAR(4000) (實際長度 < 4000),無損遷移image → 文件系統 (ASP 函數 makeattach)
- 讀取二進制流 (
ADODB.Stream Type=1 Binary)
- 按
Content-Type 判斷副檔名 (.doc/.xls/.jpg/.zip...)
- 寫入磁盤
D:\attach\attech{ID}.{ext}
- 數據庫存相對路徑/文件名
| 維度 | DTS + ODBC | 腳本 ETL (PHP/ASP) |
|---|---|---|
| 開發成本 | 零 (配置) | 中 (編寫/調試腳本) |
| 類型映射控制 | 無 (黑盒) | 完全可控 |
| 複雜類型支援 | 極弱 | 極強 (自定義邏輯) |
| 錯誤處理/重試 | 全量失敗/重來 | 行級隔離、斷點續傳 |
| 增量同步 | 困難 | 原生支援 (WHERE 條件) |
| 性能 (大表) | 一般 (單線程) | 可優化 (批次/並行/禁用索引) |
| 可審計/驗證 | 難 | 代碼即文檔、行數/Checksum 統計 |
| 適用場景 | 表少、類型簡單、一次性小遷移 | 生產級、複雜類型、增量、長期同步 |
executemany、異步並行、進度條**DTS 適合「驗證可行性」,腳本 ETL 適合「生產交付」**。作者 2003 年的親身踩坑 (ntext/image/時間戳/類型映射) 至今仍是異構遷移的**通用痛點**。現代工程應確立:**遷移即代碼、代碼即文檔、文檔即驗證、驗證可自動化**,用成熟 ETL 框架替代手工腳本,將遷移從「藝術」變為「標準化工程」。