2011|08|
2013|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|05|06|07|08|09|10|11|12|
2016|01|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|

2019-04-16 C言語プログラムでPostgreSQLの「あればUPDATE、なければINSERT」をUPSERTを使わずにやってみる。 [長年日記]

/*
 
  C言語プログラムでPostgreSQLで「あればUPDATE、なければINSERT」をUPSERTを使わずにやってみる。
 
  g++ -g db.cpp -o db -I"D:\PostgreSQL\10\include" -L"D:\PostgreSQL\10\lib" -llibpq -lwsock32 -lws2_32
 
 
  // 状態をPostgreSQLに書き込み続ける
  // プログラム実行中にも、経過情報が読めるようにする為
 
  まず、以下の手順でテーブルを作っておく
 
  C:\Users\yrl-user>psql -h localhost -U postgres	
  postgres=# \l		
  postgres=# \connect ca_db(データベース名)
  
  以下をコピペしてテーブルとその内容を直接書き込む
  
  create table q_state (
	   number int,
	   action_type int,
	   q int);
 
  ca_db=# \dt
 
  データベースのテーブルの中身を確認する
  ca_db=# select * from q_state; // 検索の基本形
 
  ======================
  本プログラムは、 
 
  (1)numberとaction_typeの値の両方が同じ行がある場合、qの値を書き換えること
  (2)同じ行がない場合には、行を追加する
 
  を実施する、かなりスマートではない方法である
  (が、とりあえずは動く)
  ======================
 
*/
 
#include 
#include 
//#include  // sleep(1)
#include  // sleep(1)
#include 
#include 
#include 
#include "libpq-fe.h"
 
 
const char *conninfo = "host=localhost user=postgres password=xxxxxxx dbname=ca_db port=5433";
PGconn *conn;
 
int open_db()
{
  // データベースとの接続を確立する 
  //PGconn *conn = PQconnectdb(conninfo);
  conn = PQconnectdb(conninfo);
  
  /* バックエンドとの接続確立に成功したかを確認する */
  if (PQstatus(conn) != CONNECTION_OK){
	fprintf(stderr, "Connection to database failed: %s",
			PQerrorMessage(conn));
  }
  
  return 0;
};
 
int delete_db()
{
  // テーブルの中身を空にする(全行を消去する)
  char stringSQL2[512] = {0};
  sprintf(stringSQL2, "DELETE FROM q_state;");
 
  PGresult *res = PQexec(conn, stringSQL2);
 
  // INSERT等値を返さないコマンドの場合戻り値は PGRES_COMMAND_OK
  if (res == NULL || PQresultStatus(res) != PGRES_COMMAND_OK) {
    // SQLコマンドが失敗した場合
	fprintf(stderr, "INSERT COMMAND IS FAILED.",
			PQerrorMessage(conn));
  }
  
  // 値セットが無い場合でも必ず結果をクリアする
  PQclear(res);
 
  return 0;
};
 
int write_db(int number, int action_type, int q)
{
  char stringSQL2[512] = {0};
  char stringSQL1[512] = {0};
  
  sprintf(stringSQL2, "UPDATE q_state SET number = %d, action_type = %d, q = %d where number = %d and action_type = %d;",
		  number, action_type, q, number, action_type);
 
  PGresult *res = PQexec(conn, stringSQL2);
  ExecStatusType est = PQresultStatus(res);
  
  char mes[10] = {0};
  strcpy(mes,PQcmdStatus(res));
 
  // UPDATEできなかった場合には、"UPDATE 0"というメッセージが帰ってくるので、
  // そのメッセージを使って、UPDATEの失敗を判断して、INSERTの処理を行う
  int c = strcmp(mes, "UPDATE 0"); 
  if (c == 0){
	sprintf(stringSQL1, "INSERT INTO q_state(number , action_type , q) VALUES(%d,%d,%d);",
			number, action_type, q);
 
	PGresult *res = PQexec(conn, stringSQL1);
  }
  
  // INSERT等値を返さないコマンドの場合戻り値は PGRES_COMMAND_OK
  if (res == NULL || PQresultStatus(res) != PGRES_COMMAND_OK) {
    // SQLコマンドが失敗した場合
	fprintf(stderr, "INSERT COMMAND IS FAILED.",
			PQerrorMessage(conn));
  }
  
  // 値セットが無い場合でも必ず結果をクリアする
  PQclear(res);
 
  return 0;
};
 
int close_db()
{
  // 最後必ずデータベースとの接続を閉じる
  PQfinish(conn);
 
  return 0;
}
 
 
int main()
{
  open_db();
  delete_db();
 
  write_db(1, 2, 4);
  write_db(1, 2, 3);
  write_db(2, 1, 4);
  write_db(2, 2, 4);
  write_db(2, 1, 5);
  write_db(1, 2, 5);
 
 
  /*
	struct timespec ts;
	fprintf(stderr, "start\n");
	ts.tv_sec = 1;
	ts.tv_nsec = 0;
	nanosleep(&ts, NULL);
	fprintf(stderr, "end\n");
  */
 
  close_db();
 
}