Perl+DBI+PostgreSQLでCGIを作っているのですが、Shift-JIS固有の字を扱いたいので、

 SET CLIENT_ENCODING TO 'SJIS';

としたのですが、特定の文字列でSQL文がエラーになります。
例えば「ソ」を

 $str = $dbh->quote( 'ソ' );

とすると、$strは「'ソ\'」になるのですが、これをSQL文中で使用すると、

 DBD::Pg::st execute failed: ERROR: unterminated quoted string at or near "'ソ\' )" at character 124

となってしまいます。
どうやら「2バイト目が5Ch(半角の\)の全角文字」+「\」+「'」と言う組み合わせの時だけエラーになるようです。
ちなみにWindows上のMySQLでは「'ソ\'」で問題ありませんでした。

これはどのように対処すればよろしいのでしょうか?
OSはRed Hat Enterprise Linux ES release 3 (Taroon Update 4) カーネル 2.4.21-4.EL
DBはPostgreSQL 7.4.7です。

よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

試しに当方の環境で試してみましたが「濱」をInsertしてHTMLで表示という流れは問題ありませんでした。


当然WHERE句に指定しても問題ありませんでした。
データベースのEncodeはEUCでHTMLはS-JISです。
SJIS表示できるターミナルでも試したのですが、最初ターミナルをEUC表示でSET CLIENT_ENCODING TO 'SJIS';を行い、ターミナルをSJIS表示に切り替えINSERTおよびSELECTしてみましたが問題ありませんでした。ターミナル上でも同様の現象が発生しますか?

この回答への補足

検証ありがとうございます。
SJISターミナルにおいてもやはり「'ソ\'」はエラーでした。「濱」の異体字(ウ冠と貝の間がちょっと違う)や「崎」の異体字(大の所が立になっている)といった文字自体そのものは問題ないのですが、それらの文字を扱う為にShift-JISにしたところ、別の「ソ」「表」「能」といった2バイト目が5Chの文字とシングルクォートの組み合わせがエラーになってしまうのです。

ちなみにこのOKWeb(教えてgoo)もこれらの文字は入力出来ないみたいですね。
Web上ではあまり歓迎されていないのでしょうか…。

補足日時:2005/04/11 12:43
    • good
    • 0

違うかもしれませんが・・・


データベースのEncodeがSQL_ASCIIになってませんか?
前に似たようなことになったことがあるのですがSQL_ASCIIだと
SET CLIENT_ENCODING TO 'SJIS';
を行ってもSJISにはなりません。
その時はEUCに変換するプログラムを作って新たなデータベース(EUC)を作成して対応しました。

この回答への補足

アドバイス、どうもありがとうございました。
「psql -l」で見た所、EncodingはEUC_JPになっていました。
Shift-JISにしたいのは、人名でEUCにはない漢字を扱いたいからなのですが(「濱」や「崎」の異体形)、こういう苗字の人には我慢してもらうしかないのでしょうか…。あと、私の場合はこの環境でしか検証出来ないのですが、この現象がここだけなのか、他のDB環境でも再現されるものなのかが気になります。

引き続き自分でも色々調べています。

補足日時:2005/04/07 17:33
    • good
    • 0

そもそもこの場合は「ソ」をquoteに掛ける必要がないでしょう。


ダブルクォートで括っている場合は展開されてしまうために「ソ」の2バイト目が\であるため文字化けしてしまいますが、シングルクォートで括った場合は展開されないので文字化けが起きません。
今回の場合、「ソ\」で2バイト目の\とquoteで付加された\で\\と続いてしまっているために打ち消されて\ひとつになってしまいエラーの原因になっていると思われます。
(Perlでは\\は文字としての\を表します)

この回答への補足

早速のアドバイス、どうもありがとうございます。
非常に役に立ちました。

ただ、文字列をSQL文内にセットする時にquoteを通さないのはあまり現実的でないような気がします。
例えばファイルを1行づづ読み込んでDBに挿入するのはよくある事だと思うのですが、1行目が「\」、2行目が「ソ」だった場合、前者はquoteを通さないとエラーになり、後者は通すとエラーになります。
通すか通さないかを判断するには文字列のバイトイメージをいちいち解析しなければならず、quote後はそれぞれ「'\\'」「'ソ\'」16進で(27 5C 5C 27) (27 83 5C 5C 27)になりますが、単に「\\'」の並びではエラーにならず、あくまで最初の「\」が「全角文字の2バイト目」の時に限ってエラーになります。
ですから「ソセ」→「'ソ\セ'」(27 83 5C 5C 83 5A 27)のように「\」と「'」が離れている時はうまく行きます。
私としては、「\\'」において1番目の「\」が単体の時は「\\」の方が「\'」よりも優先順位が高く、全角後半の時は「\\」よりも「\'」の方が高い為にこのようになってしまうのかな?とも思ったのですが。

ちなみにPerlはシングルクォートで囲む場合でも、クォートの直前に5Chが来る全角文字では「'ソ'」ではなく「'ソ\'」としないとエラーになりました。
私も自分で色々調べているのですが、よろしくお願いします。

補足日時:2005/04/05 17:38
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

Qこのような疑問文になるのでしょうか?(中学1年生の問題)

"中学1年生"の英語のワークにこのような問題がありました。「Her sister is a singer.(a singer をたずねる疑問文にしなさい)」 
解答がなくどのように解答されているか分からないのですが、中学1年生の知識をふまえて答えは「what is her sister?」にすると先生はおっしゃっておりました。                     
この疑問文で「her sister」の職業をたずねている文になっているのでしょうか?この疑問文は中学1年生の知識をふまえた上で解答として正しいのでしょうか?

Aベストアンサー

#1です。 少々質問の内容を読み間違えておりました。 #2さんの通りの回答でよろしいいのですが、イギリスに現在住んでいる人間としてアドバイスさせてもらうと、実際What is that woman?と聞く人は皆無です。 

What does her sister do?がいいと思います。 ちなみにoccupationという単語は中一の範囲ではないと思います

QPerl DBI でSELECT ilikeの結果がうまくでない

入力したワードを含む商品の列挙をしたいのですけどpsqlで直接たたくとうまく結果がでるのにPerlからDBIを使用した場合は入力ワードによってうまくできたりできなかったりします。どうしたらうまくいくのでしょうか?

DBはEUC-JP PerlからのクエリーもEUCにJcode変換してから行っております。
なおうまく出ないのは漢字ではなく英数字をワードにしたものです。

SELECT * FROM 商品テーブル WHERE 商品名 ilike '%入力ワード%'

商品名が**** A-101ABXの場合 '%A-%'ではうまくいくけど'%A-101BX%'ではうまくいかない。
(****は任意の漢字、英数字)

どうぞよろしくお願いします。

Aベストアンサー

以下のコードの実行結果はどうなりますか?
(実際の結果と、期待する結果の両方を教えてください)

$\="\n";
$sth = $dbh->prepare('select name from testtbl where name ilike ?') || die $dbh->errstr;
$sth->execute('%A99B-6%') || die $sth->errstr;
while ($name = $sth->fetchrow_arrayref()) {
last if $dbh->errstr;
print @{$name};
}
print '$dbh->errstr:'.$dbh->errstr if $dbh->errstr;
print '$sth->rows:'.$sth->rows;

Q「ぶんを通しぶんを守った」という日本語のぶんってどの漢字でどういう意味ですか? 分?文? 武のぶの聞

「ぶんを通しぶんを守った」という日本語のぶんってどの漢字でどういう意味ですか?

分?文? 武のぶの聞き間違い?

でもどれの漢字を当てはめてもそういう熟語はないと出ます。

Aベストアンサー

大義名分の分だと思うが、主張を通し正当性を守ったとか。

QSQL文で「あ」などの2バイトの文字を条件に入れるとエラーになる。

PHPとPostgreSQLでファイルを作成しました。
(2)、(3)の場合だと問題なく動作しますが、
(1)の場合だと動作しません。
「あ」が2バイトなのが原因かとおもうのですが、
よくわかりません。他に原因あるのでしょうか。

**********************************************
環境 PHP5 Apache2.2 PostgreSQL8.24
*********************************************

<?php
// 接続設定(サーバ/データベース/ユーザ/パスワード)
$sv = "localhost";
$dbname = "test";
$user = "user";
$pass = "pass";

// 文字コード
$enc_disp = "EUC-JP";
$enc_db = "EUC-JP";

// データの文字コードを変換する関数
function cnv_enc($string, $to, $from) {
// 文字コードを変換する
$det_enc = mb_detect_encoding($string, $from . ", " . $to);
if ($det_enc and $det_enc != $to) {
return mb_convert_encoding($string, $to, $det_enc);
}
else {
return $string;
}
}

// データベースに接続する
$conn = pg_connect("host=$sv dbname=$dbname
user=$user password=$pass") or die("接続エラー");

(1)$sql = "select * from test WHERE name LIKE N'あ%'";
(2)$sql = "select * from test WHERE tel LIKE N'090%'";
(3)$sql = "select * from test WHERE no LIKE N'a%'";

?>

*********************************************
nameには、名前の文字列(いとう、さとう)が、
telには、電話番号(090…、03…)が、
noには、アルファベット一文字(a、b)が
入力されています。
*********************************************

PHPとPostgreSQLでファイルを作成しました。
(2)、(3)の場合だと問題なく動作しますが、
(1)の場合だと動作しません。
「あ」が2バイトなのが原因かとおもうのですが、
よくわかりません。他に原因あるのでしょうか。

**********************************************
環境 PHP5 Apache2.2 PostgreSQL8.24
*********************************************

<?php
// 接続設定(サーバ/データベース/ユーザ/パスワード)
$sv = "localhost";
$dbname = "test";
$user = "user";
$pass = "pas...続きを読む

Aベストアンサー

>「エラーになる」、「動作しません」

どういう事象になるのか、具体的に書きましょう。
何かエラーメッセージやエラーコード類は、出ていませんか?

「WHERE tel LIKE N'090%'」の「N」の意味を知った上で、この書き方をしていますか?

Q質問文は推敲しますか?

教えて!gooに質問されたことのある方に質問です。
質問をされるときに、なるべく回答者が理解しやすいように質問文を何度も見直してから「質問する」ボタンを押しますか? それとも確認ページをろくに読まずにすぐにボタンを押しますか?
どちらなのでしょうか?

ちなみにわたしは、一応、一通り読見直してからボタンを押します。

Aベストアンサー

見直してから投稿します。
教えてgooに限らず掲示板とかでも見直しますよ。
私的には誤字とかは嫌いなので……よく文章構造がおかしくなってますし。

Qtutorial/funcs.sqlの中のSQL文

の中に

CREATE TABLE EMP (
name text,
salary integer,
age integer,
cubicle point
);

INSERT INTO EMP VALUES ('Sam', 1200, 16, '(1,1)');
INSERT INTO EMP VALUES ('Claire', 5000, 32, '(1,2)');
INSERT INTO EMP VALUES ('Andy', -1000, 2, '(1,3)');
INSERT INTO EMP VALUES ('Bill', 4200, 36, '(2,1)');
INSERT INTO EMP VALUES ('Ginger', 4800, 30, '(2,4)');

-- the argument of a function can also be a tuple. For instance,
-- double_salary takes a tuple of the EMP table

CREATE FUNCTION double_salary(EMP) RETURNS integer
AS 'SELECT $1.salary * 2 AS salary' LANGUAGE SQL;

SELECT name, double_salary(EMP) AS dream
FROM EMP
WHERE EMP.cubicle ~= '(2,1)'::point;

というコードが有るのですが
最後のWHERE EMP.cubicle ~= '(2,1)'::pointの
~=
はどういうもので
どんなときにつかうのでしょうか?
また単なる
=
ではエラーになるようなのですが=との使い分けはどのようにすれば良いのでしょうか?

よろしくお願いします

の中に

CREATE TABLE EMP (
name text,
salary integer,
age integer,
cubicle point
);

INSERT INTO EMP VALUES ('Sam', 1200, 16, '(1,1)');
INSERT INTO EMP VALUES ('Claire', 5000, 32, '(1,2)');
INSERT INTO EMP VALUES ('Andy', -1000, 2, '(1,3)');
INSERT INTO EMP VALUES ('Bill', 4200, 36, '(2,1)');
INSERT INTO EMP VALUES ('Ginger', 4800, 30, '(2,4)');

-- the argument of a function can also be a tuple. For i...続きを読む

Aベストアンサー

~= は幾何データ型の演算子で、位置や形が同じかどうかの比較になります。
幾何データ型の = は面積が同じかどうかの比較になります。

point 型は平面における座標「点」なので、面積を持たないから = が
使えないのではないかと思います。


幾何関数と演算子
http://www.postgresql.jp/document/pg904doc/html/functions-geometry.html

> "同じを示す"~=演算子はpoint、box、polygon、およびcircle型に対し通常の等価概念を示すことに注意してください。
> これらのいくつかの型は=演算子を持ちますが、=は面積の等しさのみを比較します。
> その他のスカラー比較演算子(<=など)は同様にこれらの型の面積を比較します。

幾何データ型
http://www.postgresql.jp/document/pg904doc/html/datatype-geometric.html

Q以下の文は単位量あたりの説明として正しいですか?

以下の文は単位量あたりの説明として正しいですか?

説明文:2つの異なる量の商から導き出され、前項と後項との比率を表す。
 式は、単位Aで表される量÷単位Bで表される量=単位B1当たりのAの量
  
問題:200m2の土地に50頭の牛がいます。牛1頭あたり何m2の面積を占有させられるか?
200m2÷50頭=1頭あたり4m2

問題2:20kmを2時間で走る車がある。時速は?
  20km÷2時間=時速10km/時 

Aベストアンサー

こんにちは。
この前の続きですね。
よいと思います。

もしも、「1当たり」を強調したければ、
200m2÷50頭 = 4m^2/1頭 = 1頭あたり4m2
20km÷2時間 = 10km/1時間 = 時速10km/時
というふうに書く手もありますね。

QSQLでPostgreSQLサーバーを切断させたいと考えています。なか

SQLでPostgreSQLサーバーを切断させたいと考えています。なかなかわかりません。
だれか、教えて頂ければ大変助かります。
宜しくお願い致します。

Aベストアンサー

pg_stat_activity ビューを参照すれば、実行中の SQL とその PID を特定できるので、

test=> SELECT procpid, current_query FROM pg_stat_activity;
procpid | current_query
---------+----------------------------------------------------------------
17288 | <IDLE> in transaction
17287 | UPDATE branches SET bbalance = bbalance + 1487 WHERE bid = 5;

スーパーユーザでデータベースに接続し、その PID を指定して pg_cancel_backend 関数を呼び出してあげれば、実行中の SQL をキャンセルしてサーバとの接続を切断できます。

test=> SELECT pg_cancel_backend(17287);

pg_stat_activity ビューを参照すれば、実行中の SQL とその PID を特定できるので、

test=> SELECT procpid, current_query FROM pg_stat_activity;
procpid | current_query
---------+----------------------------------------------------------------
17288 | <IDLE> in transaction
17287 | UPDATE branches SET bbalance = bbalance + 1487 WHERE bid = 5;

スーパーユーザでデータベースに接続し、その PID を指定して pg_cancel_backend 関...続きを読む

Q今読書感想文を書いているんですが、 段落っていくつしてもいいんですか?

今読書感想文を書いているんですが、
段落っていくつしてもいいんですか?

Aベストアンサー

いくつやってもいいと思いますが、話や場面変わる所で段落をすると、とてもスッキリすると思います。

QLinux+PostgreSQLでの設定

こんにちは。
Linux+PostgreSQLでpg_hba.confの設定がよく分からず困っています。
リモートからは使用せず、localhostのみの接続を許可したいのですが、
どのように設定すればいいのでしょうか?
CentOS5+PostgreSQL8.1.9です。

Aベストアンサー

マニュアルを参考にして
http://www.postgresql.jp/document/pg815doc/html/client-authentication.html#AUTH-PG-HBA-CONF
何がよく分からないのか提示してください。

質問の要件のみだったらこんな感じじゃないかな。
# TYPE DATABASE USER CIDR-ADDRESS METHOD
host all all 127.0.0.1/32 trust
trustのとこはauth-methodから選択してね。


人気Q&Aランキング

おすすめ情報