質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.93%

$result = pg_query("DB接続リソース",SQLクエリ)の結果、$resultがfalseになってしまいます

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 193

y_programming

score 18

$con = pg_connect("dbname=db0000 user=nobody");
if(!$con){
    return_error("DB接続失敗");
}

$sql = "SELECT TO_CHAR(y.yoyaku_date,'YYYY-FMMM-FMDD') AS yoyaku_date, s.sname, y.start_time, y.end_time  "
."FROM tbl_4_2_1 AS y INNER JOIN tbl_4_2_2 AS s "
."ON y.scode = s.scode "
."WHERE TO_DATE(y.yoyaku_date,'YYYY-MM')=TO_DATE('$year-$month','YYYY-MM') "
."ORDER BY s.scode,y.start_time,y.end_time";
$result = @pg_query($con,$sql);
if(!$result){
    return_error(
    "検索に失敗しました<br>
    [$result]<br>
    [$con]<br>
    [$sql]"
    );
}
    return_error(
    "検索に失敗しました<br>
    [$result]<br>
    [$con]<br>
    [$sql]"
    );


の部分はブラウザ上で以下のように表示されます。ここで$result,$con,$sqlの中身を確認しようと考えています。ここで、$resultに何も入っていない事が判明しました。

検索に失敗しました
[]
[Resource id #2]
[SELECT TO_CHAR(y.yoyaku_date,'YYYY-FMMM-FMDD') AS yoyaku_date,
 s.sname, y.start_time, y.end_time FROM table1 AS y INNER JOIN
 table2 AS s ON y.scode = s.scode WHERE TO_DATE(y.yoyaku_date,'YYYY-MM')
=TO_DATE('2020-3','YYYY-MM') ORDER BY s.scode,y.start_time,y.end_time]


以下の一行の処理により、$resultの中に$conで指定しているdb0000に対して命令を飛ばした内容が入ると思ったのですが失敗して$resultにはfalseが入っているようです。

$result = pg_query($con,$sql);

マニュアルを読んでみたところ、pg_query_params()という上位互換?と思われる
関数があった為、それも使ってみました。

$result = pg_query_params($con,$sql);


↑の結果のエラーは、
Warning: pg_query_params() expects parameter 1 to be string, resource given in ファイルパス

というものです。「パラメータ1が文字列であることを期待しています。」との事なので、
pg_query_paramsに2つ渡す引数のうち、1つ目である$conが間違っているのかなと予想しました。
$conの直近の代入である、

$con = pg_connect("dbname=db0000 user=nobody");
if(!$con){
    return_error("DB接続失敗");
}


を見直してみても、どうもここの部分はエラーに関与していないように思ってしまいます。
$conには、ブラウザ上に表示されたように「Resource id #2」という文字列が入っていると判断した為です。

エラー原因に辿り着く事が出来なかった為、何かヒントが欲しい状況です。
何かお気づきの方がいらっしゃいましたらご指摘いただきたいです。
よろしくお願いします。

環境
・postgreSQL 9.4.26
・PHP 5.3.3
・virtualBox6.1.4 r136177(Qt5.6.2)
・CentOS-6.8-x86_64-minimal.iso

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • m6u

    2020/03/30 21:59

    CentOS系なら、remiレポジトリの追加をすれば最新版PHPも入れられます。 https://rpms.remirepo.net/wizard/

    キャンセル

  • asahina1979

    2020/03/30 22:20

    なんとなくだが

    TO_DATE(y.yoyaku_date,'YYYY-MM')
    TO_DATE('2020-3','YYYY-MM')

    上記2つはのぞみのものかえってきてる?

    キャンセル

  • y_programming

    2020/04/10 23:37

    研修が始まり、このコードをpostgreSQL 8.4で動かす機会があり、原因が判明しました。

    「y.yoyaku_date」を
    「y.yoyaku_date::text」と書く事によってTO_CHAR()が正常に動きました。
    TO_CHAR()がpostgreSQLのバージョン次第で書き方が変わることがあるようです。


    asahina1979 様

    TO_DATE(y.yoyaku_date,'YYYY-MM')
    TO_DATE('2020-3','YYYY-MM')
    のうち前者が動いていなかったようです。
    ありがとうございました。
    PHPのビルトイン関数とDBMSで相性があるのは気付くのに時間がかかってしまいましたが、
    よい経験だったように思います。

    P.S.
    PHPを5から7に変えてみましたが、手元にある大量のPHPファイルの参照渡しが全て動かなくなって
    しまい、結局PHP5.3.3に戻しました。
    そのソース達は恐らく数カ月以内に使う必要がなくなるので、その後にPHP7に上げたいと思います。

    キャンセル

回答 1

checkベストアンサー

+1

文字列の連結、しかも、文字列内に変数展開も組み合わせているというのが、
想定外のクエリー文字列になっていたりしないでしょうか。

PHP: pg_prepare - Manual

を駆使してプリペアドステートメントとして安全にクエリーに実行時パラメータを与える方法で組み直してください。
その際、ヒアドキュメント構文も駆使して、
読みやすいSQLクエリーにするとよいかと。

$sql = <<<EOT
SELECT TO_CHAR(y.yoyaku_date,'YYYY-FMMM-FMDD') AS yoyaku_date, s.sname, y.start_time, y.end_time 
FROM tbl_4_2_1 AS y INNER JOIN tbl_4_2_2 AS s ON y.scode = s.scode 
WHERE TO_DATE(y.yoyaku_date,'YYYY-MM')=TO_DATE($1,'YYYY-MM') 
ORDER BY s.scode,y.start_time,y.end_time;
EOT;
$result = pg_prepare($con, 'query', $sql);
$result = pg_execute($con, 'query', array($year . '-' . $month));


(あくまで机上のコードなので、エラーが出たらご指摘を。)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/10 23:38

    すみません、他の方の書いたこのコードを動くようにする、というのが
    取り組む上での趣旨だった為、今回のクエリを理解していなかったのが主たる原因です。

    今回は原因がTO_CHARの仕様だった為なんとか事なきを得ましたが、
    SQL文に手を加える必要があったなら、現時点の自分では対処できなかったように思います。

    まずはSQLの基礎からですね・・・

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る