SQLserverへデータ入力

[戻る]
ライカ 2008/07/14(月) 10:15:36
はじめまして,C++でのDB操作でかなりてこずってます.
現在,VC++でMFCでODBCを使用してSQLserverに接続しています.

SQLServerに接続は問題なく出来るのですが
データ入力のところで以下ような問題に悩んでいます.

SQLCHAR szCommand[255] = 
("INSERT INTO DBNAME (%s) VALUES (%d)",name,data);

name:char型 data:short型

となっており,実行すると.
error C2440: '初期化中' : 'short' から 'SQLCHAR [255]' に変換できません。
といったエラーが表示されます.

このエラーを解決するにはどのようにすればいいのでしょうか??

ライカ 2008/07/14(月) 10:19:42
1行目でC++と書いてしまいましたが,VC++の間違いでした.すいません.

PATIO 2008/07/14(月) 11:05:08
バージョンはいったい何なのでしょう?

VS2005以降だったりするとデフォルトの文字コードが
UNICODEになっているのでデフォルトの文字列はWCHARだったりしたと
思いますけれど。

subaru 2008/07/14(月) 11:14:13
とりあえず文字列の初期化の方法が間違ってます。
書式指定で文字列を作るなら普通は
sprintf_s/wsprintfなどを使います。

tetrapod 2008/07/14(月) 12:05:42
そしてSQLインジェクション脆弱性を作りこむ、と。
今のうちからよく検討しておいたほうがいいよ

ライカ 2008/07/14(月) 17:27:07
>PATIOさん
バージョンは2005です.
えっと,VSのデフォルトがUNICODEで,SQLのデフォルトがWCHARAということでしょう
か?

>subaruさん
sprintf(szCommand,"〜");
みたいな感じでしょうか?
〜のところで上記のSQLの内容を書いてしまえばいいんですね?

>tetrapodさん
えっと・・・SQLインジェクション脆弱性というのがよくわからないのですが
具体的にどのようなものなのでしょうか?

soluna 2008/07/14(月) 20:28:06
>SQLCHAR szCommand[255] = 
>("INSERT INTO DBNAME (%s) VALUES (%d)",name,data);

入門書読み直した方が良いよ?

bun 2008/07/14(月) 22:30:09
エラーの意味だけは教えておきます。
以下の部分、
  "INSERT INTO DBNAME (%s) VALUES (%d)",name,data
カンマ演算子で、
  "INSERT INTO DBNAME (%s) VALUES (%d)"
  name
  data
の空処理とみなされているだけです。
で、最後の data が =演算子の戻り値として採用されています。

というわけで、エラーメッセージと合っているでしょ。
その先は、少し自分で考えてみてくださいな。

... 2008/07/14(月) 23:26:20
暑いので殺伐としてますね。

>sprintf(szCommand,"〜");
>みたいな感じでしょうか?
>〜のところで上記のSQLの内容を書いてしまえばいいんですね?

です。確認するより、まずは実行あるのみです。


>SQLインジェクション
http://ja.wikipedia.org/wiki/SQL%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3

sprintf_sについても検索してみるといいかもしれません。

ライカ 2008/07/15(火) 11:54:29
いろいろと情報ありがとうございます.

sprintf_sを使用し,以下のソースで実行してみました.

SQLCHAR szCommand[255];
sprintf_s(szCommand, 255,"INSERT INTO  airpenDB ('%s') VALUES (%d)",recog_item
[i].item_name,recog_item[i].result);

すると
int sprintf_s(char *,size_t,const char *,...)' : 1 番目の引数を 'SQLCHAR 
[255]' から 'char *' に変換できません。
というエラーが発生しました.

そこで
char szCommand[255]; 
変更し実行してみましたが,
後で書かれている
retcode = SQLExecDirect(hstmt1,szCommand,SQL_NTS);
のところで「2 番目の引数を 'char [255]' から 'SQLCHAR *' に変換できません。」
というエラーが表示されました.

char,SQLCHAR等の型をうまく合わせる方法ってなにかありますでしょうか??
自分でも色々と調べてみているのですが,良い方法がなかなか見つからないので….
よろしくお願いします.

subaru 2008/07/15(火) 13:36:17
SQLCHARはunsigned char配列なのでキャストするしかないのでは?

SQLTCHARという型もあるようだけど使えないのかな?
MFCなのでこんな感じでも動くと思います。
CStringA sql;
sql.Format("INSERT INTO  airpenDB ('%s') VALUES (%d)",recog_item
[i].item_name,recog_item[i].result);
retcode = SQLExecDirect(hstmt1,(SQLCHAR*)(LPCSTR)sql,SQL_NTS);

ODBC APIは触ったことないけどSQLインジェクションに対策するなら
SQLBindParameterあたりを使うんじゃないだろうか。

ITO 2008/07/15(火) 14:57:22
> ODBC APIは触ったことないけどSQLインジェクションに対策するなら
> SQLBindParameterあたりを使うんじゃないだろうか。
「SQLBindCol」で変数をセットします。
必要に応じてキャストします。
ODBC APIは、SQL_C_????等の型があるので合うのを選定しないといけないですね。

... 2008/07/15(火) 23:39:59
2005で確認できないのでなんですが
そんなめんどくさい型ならあえて使わなくても
いいんではないかと。


WCHAR szCommand[255];

ITO 2008/07/16(水) 11:01:40
SQLCHARって
bcp用の変数の型ですね。
SQLserver用のツ-ルの変数の型で、VC++ようの変数の型ではないですね。
まず
1. やり取りを行うデータテ−ブル変数の型を調べる。
2. 使うVC++のODBCの関数を特定する。
   MFC?、ODBC API?、ADO?
3. VC++のODBCの関数に合う変数の型を調べる。

MFCとなるとCRecordset,Database ですね。
MSDN CDの「ODBCの基礎」をよく読みましょう。
ADOは、資料は少ないですがここの過去ログにあると思います。

一番大事なことは、「データ型はSQLserverに合わせる。」ということです。

ITO 2008/07/17(木) 09:55:32
ん?
SQL文を作って保存するだけならわざわざSQLCHAR使わなくてもいいんじゃないですか?
CRecordset,Database ならLPCTSTRなんでchar型でいいんじゃないですか。

ITO 2008/07/17(木) 10:18:23
ん?
>retcode = SQLExecDirect(hstmt1,szCommand,SQL_NTS);

szCommand は、UCHARなので、
char型でSQL文を作ってキャストするだけです。

UCHAR szCommand「500」;
長文になる可能性があるので、500以上はほしいですね。
char dbuf[256];
ここにSQL文を保存する。
strcpy((char *) szCommand, dbuf);
こんな感じ

ITO 2008/07/17(木) 10:23:03
修正です。
UCHAR szCommand「500」; は UCHAR szCommand[500]; ですね。
連文すみませんです。

ITO 2008/07/17(木) 13:03:48
すみません
>char dbuf[256];
これも500以上ほしいですね。
char dbuf[500];
こうですね。

ライカ 2008/07/17(木) 17:25:38
[[解決]]
すいません,報告遅れました.
subaruさんに教えていただいた方法を少し変更し,
以下の方法でデータ入力に成功しました.

char szCommand[255];
sprintf_s(szCommand, 255,"INSERT INTO  airpenDB (%s) VALUES (%d)",recog_item
[i].item_name,recog_item[i].result);
                    
retcode = SQLExecDirect(hstmt1,(SQLCHAR*)(LPCSTR)szCommand,SQL_NTS);

色々とありがとうございました.

古いスレッドには追加発言できません。