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

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

新規登録して質問してみよう
ただいま回答率
87.20%
Oracle Database 11g

Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

解決済

OracleDBのNumber型に文字列をInsertするとNullが入ってしまう

Kiri_Tanpo
Kiri_Tanpo

総合スコア0

Oracle Database 11g

Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

1回答

0評価

0クリップ

8340閲覧

投稿2018/03/30 02:49

編集2022/01/12 10:58

前提・実現したいこと

2度目の質問投稿になってしまい、すいませんがよろしくお願いいたします。

OracleDBにADODB経由でアクセスし、バインド変数でカラムデータを指定して、
Insert文を実行しています。
データ型がNumberのカラムに空白でない文字列を指定すると、Nullが入ってしまう原因を知りたい。

発生している問題・エラーメッセージ

データ型がNumberのカラムに空白でない文字列を指定すると、
エラーが発生せず、正常終了してしまう。
テーブルを確認すると(Null)が入ってしまっている。

該当のソースコード

vbs

'バッチホームディレクトリパス Dim BATCH_HOME Dim DATA_DIR Dim INSERT_INI Dim LOG_FILE Dim CONTROL_FLAG Dim COMPLETED_DIR Dim END_CODE'終了コード 'DB名 Private Const DATABASE = "XE" 'ユーザー名 Private Const DB_UID = "scott" 'パスワード Private Const DB_PWD = "tiger;" 'DB接続関係の定数 Private Const adDouble = 5 Private Const adDBDate = 7 Private Const adNumeric = 131 Private Const adVarChar = 200 Private Const adCmdText = 1 Private Const adParamInput = 1 Private Const adUseClient = 3 Private Const adOpenStatic = 3 ~定数でエラーコード番号をセット~ Private Const TABLESQL = "select COLUMN_NAME,DATA_TYPE,DATA_LENGTH from user_tab_columns where table_name = ? Order by COLUMN_ID" '共通変数 宣言 Public objADO Public objFSO Public objLogFile Public objIniFile Public objCsvDataFile 'cmdからの引数を受け取る ~ファイルパス取得~ '終了コード初期化 END_CODE = 0 '--------------------------------------------------------------------- ' 日時設定 '--------------------------------------------------------------------- ~~ '--------------------------------------------------------------------- ' ログファイルオープン '--------------------------------------------------------------------- ~~ '------------------------------------------------------------------' ' Iniファイル確認 '------------------------------------------------------------------' ~Iniファイルが存在しなければ、処理を終了する~ '------------------------------------------------------------------' ' DBコネクションの確立 '------------------------------------------------------------------' Dim Connection Dim objADODbConnErr Set objADO = CreateObject("ADODB.Connection") Connection = "Provider=OraOLEDB.Oracle;Data Source=" & DATABASE & ";User ID=" & DB_UID & ";Password=" & DB_PWD 'タイムアウト時間 無制限 objADO.ConnectionTimeout = 0 objADO.Open Connection 'DBコネクションが取得できない場合 ~エラーログ出力~ 'CSVファイル挿入のため、トランザクション開始 objADO.BeginTrans '--------------------------------------------------------------------- ' DATAフォルダ内のファイル情報取得(ファイル数分繰返し) '--------------------------------------------------------------------- Dim objDataFile Dim cntDataFile'処理ファイル数カウンタ Dim strIniLine Dim strInsertSql cntDataFile = 0 Dim iniReadContinue For Each objDataFile In objFSO.GetFolder(DATA_DIR).Files : For iniReadContinue = 1 To 1  ' ファイルの拡張子がCSV以外だったら、次のファイル情報へContinue  ~~  ' Csvファイル処理開始ログ出力  ~~  '---------------------------------------------------------------------  ' Iniファイルデータ情報取得(Iniファイルのレコード数分繰返し)  '---------------------------------------------------------------------  Set objIniFile = objFSO.OpenTextFile(INSERT_INI)  Do Until objIniFile.AtEndOfStream   '------------------------------------------------------------'   ' Iniファイル定義情報とCSVファイル名のマッチング   '------------------------------------------------------------'   strIniLine = objIniFile.ReadLine   strInsertSql = Mid(strIniLine, Instr(strIniLine, "=") + 1)   'Csvファイル名がIniファイル内のCSVファイル名と一致しない場合、次のIniファイル行へContinue   If Left(strIniLine, Instr(strIniLine, "=") - 1) & ".csv" = objDataFile.Name Then    Exit Do   End If   '一致しなかった場合、INSERT分を空白で初期化する   strInsertSql = ""  Loop  objIniFile.close  'SQL文が空白の場合、INIからSQL文を取得できなかったため、エラーとする  ~~  '------------------------------------------------------------'  ' Insert対象テーブル情報取得  '------------------------------------------------------------'  Dim objCMD  Dim objRs  Dim objADOErrItem  Set objCMD = CreateObject("ADODB.Command")  objCMD.ActiveConnection = objADO  objCMD.CommandText = TABLESQL  objCMD.CommandType = adCmdText  Dim param  Set param = objCMD.CreateParameter(0, adVarChar, adParamInput, 30)  param.Value = Left(strIniLine, Instr(strIniLine, "=") - 1)  objCMD.Parameters.Append param  Set objRs = CreateObject("ADODB.Recordset")  objRs.CursorLocation = adUseClient  objRs.CursorType = adOpenStatic  objRs.Open objCMD  'DBに対象テーブルが存在しなかった場合のエラー処理  ~~  '------------------------------------------------------------'  ' CSVファイルデータ情報取得(CSVファイルのレコード数分繰返し)  '------------------------------------------------------------'  Dim csvReadContinue  Set objCsvDataFile = objFSO.OpenTextFile(objDataFile.Path, 1, False)  Dim cntLoop  cntLoop = 0  END_CODE = 0  Do Until objCsvDataFile.AtEndOfStream : For csvReadContinue = 1 To 1   Dim tmp   Dim aryCsvResult   tmp = objCsvDataFile.ReadLine   aryCsvResult = Split(tmp, ",")   ' CSV読込カウンタが0(1行目)の場合、ヘッダー行の為、次のCSVデータ行へContinue   ~~   'CSVデータと、SQL文の項目一致チェック   ~~   '------------------------------------------------------------'   ' CSVのデータ内容をSQLにバインドし、SQL実行   '------------------------------------------------------------'   Set objCMD = CreateObject("ADODB.Command")   objCMD.ActiveConnection = objADO   objCMD.CommandText = strInsertSql   objCMD.CommandType = 1   Dim paramNum   paramNum = 0   objRs.MoveFirst   Do Until objRs.EOF    Dim columnType    columnType = getColumnType(objRs.Fields("DATA_TYPE").Value)    Set param = objCMD.CreateParameter(paramNum, columnType, adParamInput, objRs.Fields("DATA_LENGTH").Value ) ~①~    If Trim(aryCsvResult(paramNum)) = "" Then     param.Value = null    Else     param.Value = aryCsvResult(paramNum)    End If    objCMD.Parameters.Append param    paramNum = paramNum + 1    objRs.MoveNext   Loop   Err.Number = 0   objCMD.Execute()   '------------------------------------------------------------'   ' SQL実行時エラーの確認   '------------------------------------------------------------' ~追記~   If Err.Number <> 0 Then    '--------------------------------------------------------'    'SQLエラー情報のログ出力    '--------------------------------------------------------'    Set objADOErrItem = objADO.Errors.Item(0)    ~エラーログ出力~    If objADOErrItem.NativeError = "ORA-00060" Then     END_CODE = ERR_DeadLouk    Else     END_CODE = ERR_SQL    End If    Set objADOErrItem = Nothing    '--------------------------------------------------------'    'INSERT失敗処理    '--------------------------------------------------------'    objCsvDataFile.Close    objADO.RollbackTrans    Call NgInsert( objDataFile.Path )    ExitProc ( END_CODE )    objCMD.Close    Set objCMD = Nothing    Exit Do   End If   Set objCMD = Nothing   ' CSV読込カウンタ   cntLoop = cntLoop + 1  Next : Loop  If END_CODE = 0 Then   '--------------------------------------------------------'   'INSERT成功処理   '--------------------------------------------------------'   objCsvDataFile.Close   objADO.CommitTrans   Call OkInsert( objDataFile.Path )  End If  ' 処理ファイル数カウンタ  cntDataFile = cntDataFile + 1  objIniFile.Close  'CSVファイル挿入のため、トランザクション開始  objADO.BeginTrans Next : Next ~ログを出力後、オブジェクトをClose、破棄し、終了コードをBatchに返す~ '--------------------------------------------------------------------- ' エラー処理関数 '--------------------------------------------------------------------- ~追記~ Sub ExitProc(END_CODE)  'データベースを閉じる  objCMD.Close  objCsvDataFile.Close  If CONTROL_FLAG = 0 Then   objADO.Close   Set objDataFile = Nothing   Set objDataFolder = Nothing   Set objFSO = Nothing   Set objLogFile = Nothing   Set objCsvDataFile = Nothing   WScript.Quit(END_CODE)  End If End Sub '--------------------------------------------------------------------- ' INSERT成功処理 '--------------------------------------------------------------------- ~CSVファイルリネーム処理~ '--------------------------------------------------------------------- ' INSERT失敗処理 '--------------------------------------------------------------------- ~CSVファイルリネーム処理~ '--------------------------------------------------------------------- ' INSERTSQLと、CSVデータの項目件数一致判定処理 '--------------------------------------------------------------------- ~一致していたら、Trueを返す~ '--------------------------------------------------------------------- ' データタイプ判定処理 ' iType : Oracleテーブル定義の型情報 '--------------------------------------------------------------------- Public Function getColumnType ( iType ) Dim retVal Select Case iType Case "VARCHAR2" retVal = adVarChar Case "NUMBER" retVal = adNumeric Case "BINARY_FLOAT" retVal = adDouble Case "BINARY_DOUBLE" retVal = adDouble Case Else retVal = adVarChar End Select getColumnType = retVal End Function

試したこと

現在は、上記ソースの①の部分でIf文をかませてエラーを発生させるよう誘導していますが、
なんでNullが入ってしまうのか原因がわからないので、再度投稿しています。

vbs

'数字項目に文字が入っていた場合 If columnType = adNumeric And Not IsNumeric(Trim(aryCsvResult(paramNum))) And Not Trim(aryCsvResult(paramNum)) = "" Then  'error処理  'エラーメッセージ出力  END_CODE = ERR_SQL  Exit Do End If

補足情報(FW/ツールのバージョンなど)

設定ファイルに下記のようにInsert文の雛形をおいています。
CSVファイル名=INSERT INTO "テーブル名" ("カラム名1","カラム名2",‥) values (?,?,‥)
cmdファイルをたたいてVBSを呼び出しています。
設定ファイル内のCSVファイル名とディレクトリ内のCSVファイルを比較して、マッチングしたらInsert文を引っ張ってきて、CSVファイルの読込を始め、上記問題のソースでパラメータに実際のデータをセットしています。

Windows7
OracleDB 11g
VBScript
Batch

良い質問の評価を上げる

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

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

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

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

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

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

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

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

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

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

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

Oracle Database 11g

Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。