| PostgreSQL | ||
|---|---|---|
| 上一頁 | 下一頁 | |
COPY ─ 在表和文件之間拷貝數據
COPY [ BINARY ] table [ WITH OIDS ]
FROM { 'filename' | stdin }
[ [USING] DELIMITERS 'delimiter' ]
[ WITH NULL AS 'null string' ]
COPY [ BINARY ] table [ WITH OIDS ]
TO { 'filename' | stdout }
[ [USING] DELIMITERS 'delimiter' ]
[ WITH NULL AS 'null string' ]
注意:對於拷貝入(copy in),任何匹配這個字串的字串將被儲存為 NULL 值,所以你應該確保你用的字串和拷貝出(copy out)相同。
COPY 在 Postgres 表和標準 Unix 文件之間交換數據。COPY 指示 Postgres 後端直接從文件中讀寫數據。該文件必須為後端可見,而且文件名必須從後端的角度聲明。如果聲明的是 stdin 或 stdout,數據通過客戶前端流到後端。
BINARY 關鍵字將強制使用二進制對像而不是文本儲存/讀取所有數據。這樣做在一定程度上比傳統的拷貝命令快,但移植性不是很好,而且產生的文件也較大(盡管這個方面與數據本身密切相關)。預設地,文本拷貝使用 tab ("\t")字符作為分隔符。分隔符仍然可以用關鍵字 USING DELIMITERS 改成任何其它的字符。在數據中的與分隔符相同的字符將用引號引起。
你對任何要 COPY 出來的數據必須有select權限,對任何要 COPY 入數據的表必須有inser和update權限。使用 COPY 時後端同樣需要適當的對文件操作的 Unix 權限。
關鍵字 USING DELIMITERS 聲明一個作為所有列的分隔符的字符。如果在分隔符字串裡聲明了多個字符,只使用第一個字符。
小技巧: 不要把 COPY 和 psql 的命令\copy 混淆。
COPY 不會激活規則,也不會處理字段預設值。不過它的確激活觸發器。
COPY 在第一個錯誤處停下來。這些在 COPY FROM 中不應該導致問題,但在 COPY TO 時目的表會部分改變。應該在一次失敗的拷貝後用 VACUUM 查詢做一些清除工作。
因為 Postgres 後端的工作目錄通常和用戶的工作目錄不一樣,本地用戶向一個文件"foo"(沒有附加的路徑資訊)可能會產生不可預見的結果。這時,foo 將產生在 $PGDATA/foo。 通常,聲明拷貝文件時要加上相對後端伺服器的全路徑。
作為 COPY 參數聲明的文件名必須存在與資料庫伺服器可訪問的地方,不管是在本地硬盤還是在網路文件系統上。
如果使用了一個從一台機器到另一台機器的 TCP/IP 連接,而且聲明了目標文件,那麼目標文件將會寫到後端運行的機器上,而不是用戶的機器上。
當不帶 BINARY 選項使用 COPY TO 時,產生的文件每條記錄占據一行,每列(字段)用分隔符分開。內嵌的分隔符將由一個反斜杠("\")開頭。字段值本身是由與每個字段型態相關的輸出函數產生的字符串。某一型態的輸出函數本身不應該產生反斜杠﹔這個任務由 COPY 本身完成。
每個記錄的實際格式是
<attr1><separator><attr2><separator>...<separator><attrn><newline>
如果聲明了 WITH OIDST,它將被放在每行的開頭。
如果 COPY 將它的輸出輸出到標準輸出而不是一個文件,它將在每個換行符前輸出一個反斜杠("\")和一個句點(".")作為行間隔。類似,如果 COPY 從標準輸入讀入數據,它將把一行開頭的由一個反斜杠("\")和一個句點(".")和一個換行符組成的這三個連續字符作為文件結束符。不過,如果在這三個字符組合之前碰到一個真的EOF(文件結束符) COPY 將結束 terminate (接著就是後端自身)。
反斜杠有其他的含義。NULL屬性輸出為"\N"。 一個反斜杠字符輸出成兩個連續的反斜杠 ("\\")一個tab字符用一個反斜杠後面跟一個tab代表。 一個新行字符用一個反斜杠和一個新行代表。當裝載不是由Postgres 產生的文件時,你需要將反斜杠字符 ("\")轉換成雙反斜杠("\\")以保証正確裝載。(出於兼容性考慮,順序的 "\N" 將總是被解釋成一個反斜杠和一個 "N"。更通用的解決方法是 "\\N"。)
當使用 COPY BINARY,文件的頭四個字節將是文件中記錄的個數。如果數值是零, COPY BINARY 命令將一直讀到文件尾。否則,它將在達到個數時停止讀取。文件中剩餘的數據將被忽略。
文件中每一實例的格式如下表。要注意本格式一定要 完全 符合。無符號的四字節整數數量在下表中稱做 uint32 。
表 14-1. 二進制拷貝文件的內容
| 文件開始 | |
| uint32 | 記錄個數 |
| 每條記錄 | |
| uint32 | 記錄數據總長 |
| uint32 | oid (如果聲明了) |
| uint32 | null 字段的個數 |
| [uint32,...,uint32] | 字段個數(attribute numbers of attributes), 從0開始 |
| - | <字段數據> |
在Sun-3s,2-字節字段以2-字節為界對齊,而所有整數字段以4-字節為界對齊。字符字段以1-字節為界對齊。在大部分其他機器上,所有大於1字節的整數是按照4-字節為邊界對齊的。注意,變長字段由字段長度在前﹔數組只是簡單的數組元素型態的連續流。
下面的例子將一個表拷貝到標準輸出,使用豎直條("|")作為域分隔符:
COPY country TO stdout USING DELIMITERS '|';
從一個 Unix 文件中拷貝數據到表 "country":
COPY country FROM '/usr1/proj/bray/sql/country_data';
這裡是一些可以從標準輸入 stdin 輸入的數據的例子(所以在最後有結束符):
AF AFGHANISTAN AL ALBANIA DZ ALGERIA ... ZM ZAMBIA ZW ZIMBABWE \.
同樣的數據,輸出到一個Linux/i586機器的二進制文件中去。數據是用 Unix 應用 od -c 顯示的。表裡有三個域﹔第一個是char(2) 第二個是 text。所有記錄在第三字段有空(null)值。注意 char(2) 字段是如何用空(null)補齊成四個字節的以及text字段是如何前面補長度的:
355 \0 \0 \0 027 \0 \0 \0 001 \0 \0 \0 002 \0 \0 \0
006 \0 \0 \0 A F \0 \0 017 \0 \0 \0 A F G H
A N I S T A N 023 \0 \0 \0 001 \0 \0 \0 002
\0 \0 \0 006 \0 \0 \0 A L \0 \0 \v \0 \0 \0 A
L B A N I A 023 \0 \0 \0 001 \0 \0 \0 002 \0
\0 \0 006 \0 \0 \0 D Z \0 \0 \v \0 \0 \0 A L
G E R I A
... \n \0 \0 \0 Z A M B I A 024 \0
\0 \0 001 \0 \0 \0 002 \0 \0 \0 006 \0 \0 \0 Z W
\0 \0 \f \0 \0 \0 Z I M B A B W E
在SQL92裡沒有 COPY 語句。
| 上一頁 | 首頁 | 下一頁 |
| COMMIT | 開頭 | CREATE AGGREGATE |