可以使用類似這樣的命令進行導(dǎo)入:
創(chuàng)新互聯(lián)公司網(wǎng)站設(shè)計,為客戶量身定制各類網(wǎng)站建設(shè)業(yè)務(wù),包括企業(yè)型、電子商務(wù)型、響應(yīng)式網(wǎng)站、行業(yè)門戶型等各類網(wǎng)站,實戰(zhàn)經(jīng)驗豐富,成功案例眾多。以客戶利益為出發(fā)點,創(chuàng)新互聯(lián)公司網(wǎng)站制作為客戶規(guī)劃、按需網(wǎng)站制作符合企業(yè)需求、帶有營銷價值的網(wǎng)絡(luò)建站方案認真對待每一個客戶,我們不用口頭的語言來吹擂我們的優(yōu)秀,千余家的成功案例見證著我們的成長。
1
2
3
4
5
6
7
8
9
copy
target_table_name
(field_1,
field_2,
field_3)
from
'C:\sourceData.txt'
with
(
FORMAT
csv,
DELIMITER
',',
escape
'\',
header
true,
quote
'"',
encoding
'UTF8')
這里,
with后面括號中跟的是導(dǎo)入?yún)?shù)設(shè)置:
format指定導(dǎo)入的文件格式為csv格式
delimiter指定了字段之間的分隔符號位逗號
escape指定了在引號中的轉(zhuǎn)義字符為反斜杠,這樣即使在引號字串中存在引號本身,也可以用該字符進行轉(zhuǎn)義,變?yōu)橐话愕囊栕址皇亲侄谓K結(jié)
header
true:指定文件中存在表頭。如果沒有的話,則設(shè)置為false
quote指定了以雙引號作為字符串字段的引號,這樣它會將雙引號內(nèi)的內(nèi)容作為一個字段值來進行處理
encoding指定了文件的編碼格式為utf8,
如果是別的格式則修改為適當?shù)木幋a格式.
PostgreSQL中的bytea字段類型可以以二進制的形式存儲數(shù)據(jù),這樣做的好處就是可以將原本存儲在網(wǎng)站目錄下的文件存儲到數(shù)據(jù)庫中,壞處就是如果文件過多、過大的話,就會導(dǎo)致數(shù)據(jù)庫的數(shù)據(jù)量大大增加,備份和恢復(fù)的時候就會浪費大量的時間,而且數(shù)據(jù)也有可能會出錯。個人覺得,在文件量小的情況下,使用這種存儲方式還是很方便的。
言歸正傳,下面介紹一下使用bytea字段存讀取文件的具體實現(xiàn)方法。首先是文件存儲于存儲于bytea字段的方法,主要用到的就是PHP中的pg_escape_bytea方法,代碼如下:
?php
$dbconn = pg_connect("host='localhost' dbname='dbname' user='user' password='password' port='port'")
OR DIE('Could not connect:' . pg_last_error());
$fileUrl = iconv("utf-8", "gbk", $fileUrl);//$fileName為文件路徑地址,漢字可能會亂碼,此處處理一下
$fileContents = file_get_contents($fileUrl);
$escapeBytea = pg_escape_bytea($fileContents);//轉(zhuǎn)義bytea數(shù)據(jù)類型的二進制字符串
$insertStr = "INSERT INTO tableName(id, contents)
VALUES(DEFAULT, '{$escapeBytea}')";
pg_query($dbconn, $insertStr);
?
從bytea字段中還原文件用到的是PHP中的pg_unescape_bytea方法,實現(xiàn)代碼如下:
?php
$dbconn = pg_connect("host='localhost' dbname='dbname' user='user' password='password' port='port'")
OR DIE('Could not connect: ' . pg_last_error());
$selectStr = "SELECT contents
FROM tableName
WHERE id = " . $fileId;//$fileId為文件id
$query = pg_query($dbconn, $selectStr);
while($row = pg_fetch_array($query, null, PGSQL_ASSOC)){
$escapeBytea = $row['contents'];
$fileContents = pg_unescape_bytea($escapeBytea); //獲得二進制數(shù)據(jù)
file_put_contents($fileName, $fileContents); //$fileName為帶有后綴名的文件名,如hello.pdf
}
?
導(dǎo)出文件后,如果二進制數(shù)據(jù)轉(zhuǎn)碼錯誤就會出現(xiàn)文件打不開的現(xiàn)象,比如錯誤的PDF文件打開時彈出錯誤如下圖:
這種錯誤在數(shù)據(jù)庫遷移時特別容易出現(xiàn)(本人是從PostgreSQL 8.4遷移到9.1),解決的方法是修改PostgreSQL的配置文件
postgresql.conf,將bytea_output的輸出類型設(shè)置為轉(zhuǎn)義類型(escape)輸出,即bytea_output = 'escape'(如果前面有#,刪除開啟配置),然后reload一下PostgreSQL的配置使修改生效,這樣二進制數(shù)據(jù)就可以正常解碼并輸出到文件。
使用預(yù)處理.估計%應(yīng)該用轉(zhuǎn)義字符..用預(yù)處理安全防止sql注入..具體方法如下:
//conn = DBUtil.getInstance().getConnection();這個是獲取conn的一個方法
//DBUtil.getInstance().close(pstmt, conn);這個是我關(guān)閉pstmt conn的方法
//關(guān)鍵就是使用PreparedStatement 這個預(yù)處理。要導(dǎo)入包import java.sql.PreparedStatement;
public void addStudent(BufferedReader br){
String name = null;
String sex = null;
String age = null;
String id = creatId();
Connection conn =null;
PreparedStatement pstmt = null;
System.out.println("請輸入學生相應(yīng)的信息:");
try {
//從鍵盤輸入學生名稱
System.out.println("請您輸入學生姓名 :");
name = br.readLine();
//從鍵盤輸入性別
System.out.println("請您輸入學生性別 :");
sex = br.readLine();
//從鍵盤輸入年齡
System.out.println("請您輸入學生年齡 :");
age = br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// System.out.println(name + sex + age);
// insertStudent(name,sex,age);
conn = DBUtil.getInstance().getConnection();
//通過輸出判斷conn是否正確
// String sql = "insert into t_student(id,name,sex,age) values(111,"+"'"+name+"','"+sex+"',"+age+")";
String sql = "insert into t_student(id,name,sex,age) values(?,?,?,?)";
try {
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, id);
pstmt.setString(2, name);
pstmt.setString(3, sex);
pstmt.setString(4, age);
pstmt.execute();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DBUtil.getInstance().close(pstmt, conn);
System.out.println("記錄插入成功");
}
如果還有疑問聯(lián)系我:qq 6 0 3 051135
使用預(yù)處理.估計%應(yīng)該用轉(zhuǎn)義字符..用預(yù)處理安全防止sql注入..具體方法如下:
//conn = DBUtil.getInstance().getConnection();這個是獲取conn的一個方法
//DBUtil.getInstance().close(pstmt, conn);這個是我關(guān)閉pstmt conn的方法
//關(guān)鍵就是使用PreparedStatement 這個預(yù)處理。要導(dǎo)入包import java.sql.PreparedStatement;
public void addStudent(BufferedReader br){
String name = null;
String sex = null;
String age = null;
String id = creatId();
Connection conn =null;
PreparedStatement pstmt = null;
System.out.println("請輸入學生相應(yīng)的信息:");
try {
//從鍵盤輸入學生名稱
System.out.println("請您輸入學生姓名 :");
name = br.readLine();
//從鍵盤輸入性別
System.out.println("請您輸入學生性別 :");
sex = br.readLine();
//從鍵盤輸入年齡
System.out.println("請您輸入學生年齡 :");
age = br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// System.out.println(name + sex + age);
// insertStudent(name,sex,age);
conn = DBUtil.getInstance().getConnection();
//通過輸出判斷conn是否正確
// String sql = "insert into t_student(id,name,sex,age) values(111,"+"'"+name+"','"+sex+"',"+age+")";
String sql = "insert into t_student(id,name,sex,age) values(?,?,?,?)";
try {
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, id);
pstmt.setString(2, name);
pstmt.setString(3, sex);
pstmt.setString(4, age);
pstmt.execute();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DBUtil.getInstance().close(pstmt, conn);
System.out.println("記錄插入成功");
}
PostgreSQL 提供了三種實現(xiàn)模式匹配的方法:傳統(tǒng) SQL 的 LIKE 操作符、SQL99 新增的 SIMILAR TO 操作符、 POSIX 風格的正則表達式。另外還有一個模式匹配函數(shù) substring可用,它可以使用 SIMILAR TO 風格或者 POSIX 風格的正則表達式
LIKE
string LIKE pattern [ESCAPE escape-character]
string NOT LIKE pattern [ESCAPE escape-character]
每個 pattern 定義一個字符串的集合。如果該 string 包含在 pattern 代表的字符串集合里,那么 LIKE 表達式返回真。和我們想像的一樣,如果 LIKE 返回真,那么 NOT LIKE 表達式將返回假,反之亦然。一個等效的表達式是 NOT (string LIKE pattern) 。
如果 pattern 不包含百分號或者下劃線,那么該模式只代表它本身;這時候 LIKE 的行為就像等號操作符。在 pattern 里的下劃線(_)匹配任何單個字符;而一個百分號(%)匹配零或多個任何字符。
一些例子:
'abc' LIKE 'abc' true
'abc' LIKE 'a%' true
'abc' LIKE '_b_' true
'abc' LIKE 'c' false
LIKE 模式匹配總是覆蓋整個字符串。要匹配在字符串內(nèi)部任何位置的序列,該模式必須以百分號開頭和結(jié)尾。
要匹配下劃線或者百分號本身,在 pattern 里相應(yīng)的字符必須前導(dǎo)逃逸字符。缺省的逃逸字符是反斜杠,但是你可以用 ESCAPE 子句指定一個。要匹配逃逸字符本身,寫兩個逃逸字符。
請注意反斜杠在字符串文本里已經(jīng)有特殊含義了,所以如果你寫一個包含反斜杠的模式常量,那你就要在 SQL 語句里寫兩個反斜杠。因此,寫一個匹配單個反斜杠的模式實際上要在語句里寫四個反斜杠。你可以通過用 ESCAPE 選擇一個不同的逃逸字符來避免這樣;這樣反斜杠就不再是 LIKE 的特殊字符了。但仍然是字符文本分析器的特殊字符,所以你還是需要兩個反斜杠。
我們也可以通過寫成 ESCAPE '' 的方式關(guān)閉逃逸機制,這時,我們就不能關(guān)閉下劃線和百分號的特殊含義。
關(guān)鍵字 ILIKE 可以用于替換 LIKE ,令該匹配就當前的區(qū)域設(shè)置是大小寫無關(guān)的。這個特性不是 SQL 標準,是 PostgreSQL 擴展。
操作符 ~~ 等效于 LIKE ,而 ~~* 等效于 ILIKE 。還有 !~~ 和 !~~* 操作符分別代表 NOT LIKE 和 NOT ILIKE 。所有這些操作符都是 PostgreSQL 特有的.
例子: 查找數(shù)據(jù)庫中表的名字(查找以tbl_開頭的表的名字)
select tablename from pg_tables where tablename like 'tbl!_%'ESCAPE '!';
利用escape轉(zhuǎn)義: 上面的sql語句中就是將!作為轉(zhuǎn)義字符,作用是將"_"轉(zhuǎn)換成普通的"_"
MySQL數(shù)據(jù)庫遷移到PostgreSQL
查了不少資料,也嘗試了一些,最后采用的辦法如下:
1. 導(dǎo)出mysql表定義(無數(shù)據(jù))
mysqldump --no-data [dbname] dbdef.sql
2. 使用mysql2postgres把腳本轉(zhuǎn)換為pgsql
3. 上面生成的腳本還不一定很完美,可以嘗試導(dǎo)入pgsql,調(diào)試錯誤并手動修改之。我遇到的問題就只有一個,mysql列定義中的zerofill需要手工去掉。一些unsinged定義會生成constraint,如果不需要可以去掉。另外,trigger都有問題,只能后面手工重建
4. 導(dǎo)出mysql數(shù)據(jù):
mysqldump -v -nt --complete-insert=TRUE --compact --no-create-info --skip-quote-names [dbname] dbdata.sql
老一些版本的pgsql如果不支持批量插入的話還需要加上--extended-insert=FALSE,這個性能損失巨大。
5. 轉(zhuǎn)義符
mysql默認字符串里的'\'是轉(zhuǎn)義符,而pgsql默認不是,修改postgresql.conf:
backslash_quote = on
escape_string_warning = off
standard_conforming_strings = off
數(shù)據(jù)導(dǎo)入完成后可以改回默認值。
5. pgsql里導(dǎo)入表定義和數(shù)據(jù)
psql -d [dbname] dbdef.sql
psql -d [dbname] dbdata.sql
6. 重建trigger
7. 自增主鍵(字段)的處理
由于導(dǎo)入數(shù)據(jù)時此字段都是有值的,所以pgsql里面seq并不會增加,可以用如下語句設(shè)置自增列的當前值:
SELECT setval('sample_id_seq',max(id)) from sample;