2016-04-07 13 views
1

ColdFusionを使用していて、特定のアカウントの特定の列の値を取得できるようにしようとしています(各アカウントは、行)。クエリ列がcfqueryparam変数であるときにcfqueryから単一の出力を取得する

このような機能が正常に動作します:

<cffunction name="getColumnValueFromAccount" access="public" returntype="string" > 
    <cfargument name="accountName" type="string" required="yes" /> 

    <cfquery name="getColumn" datasource="mydatasource"> 
     <!--- Note that the line below is 'hard-coded.' ---> 
     SELECT role_ExampleSystem 
     FROM table_name 
     WHERE (accountName = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#accountName#'>) 
    </cfquery> 

    <!--- It's easy to return the column value when you know what its name was. ---> 
    <cfreturn getColumn.role_ExampleSystem > 

</cffunction> 

しかし、私は実際に欲しいのは私がからの読み取りにどの列名を指定することができる機能である、とほとんど同一のCFの束を作るための必要性を排除別のハードコードされたSELECTパラメータを持つ関数です。私はそれがこのようなものに見えるべきだと思っていますが、私はそれが復帰しているはずだと信じている単一の文字列を実際に読むのに問題があります。

<cffunction name="getColumnValueFromAccount" access="public" returntype="string" > 
    <cfargument name="accountName" type="string" required="yes" /> 
    <!--- Trying to accept a column name as an argument ---> 
    <cfargument name="columnName" type="string" required="yes" /> 

    <cfquery name="getColumn" datasource="mydatasource"> 
     <!--- I'm trying to use cfqueryparam to add specify the column name to select. ---> 
     SELECT <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#columnName#'> 
     FROM table_name 
     WHERE (accountName = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#accountName#'>) 
    </cfquery> 

    <!--- This line doesn't work. ---> 
    <cfreturn getColumn[#columnName#] > 

</cffunction> 

私はあなたが誰かがcommentでそれを言及しているためgetColumn[#columnName#]またはgetColumn[columnName]のようなブラケット表記で変数を使用することができましたことを考えました。しかし、自分で変数を使用しようとすると、期待通りに機能しませんでした。

The value returned from the getColumnValueFromAccount function is not of type string. If the component name is specified as a return type, it is possible that either a definition file for the component cannot be found or is not accessible.

私はcfqueryタグの単一の結果を取得したいとき、私が取るべきルート任意のアイデアを、私は私のSELECT部分​​にハードコーディングされた列名を使用していない:私はこのエラーを取得しますクエリ?通常、このプロセスは非常に簡単ですが、列名が変数である場合は少し違うように見えます。

+0

* cfqueryparamを使用して、選択する列名を指定しようとしています*あなたはそうすることはできません。 CFQueryparamは、リテラルでのみ使用でき、SQLコマンドとして評価する必要のあるもの(表名や列名など)では使用できません。 – Leigh

+0

これは問題の一部であり、技術的には、cfNameのcfargumentは別のサーバー側の関数で指定するものなので、cfqueryparamが提供するSQLインジェクションの保護は必要ありません。私はそれが私が書いた何か有効なものであることを知っているので、入力をきれいにする必要はありません。 – Ectropy

+1

あなたが提案した 'cfqueryparam'を削除し、'#変数# 'で置き換え、Mark A Krugerの括弧表記の使い方の修正例を使用しました。それは期待どおりに動作しているようです!私は将来的に人々を助ける場合に備えて、私が最後に持っているものを投稿します。 – Ectropy

答えて

1

マイソリューション:私はそれを使用しようとしていた方法でcfqueryparamを使用することはできませんリーのアドバイス、そしてマーク・A・クルーガーのanswerに基づいて

私は自分のコードを変更し、それが働いて得ることができました。それは次のようになります。

<cffunction name="getColumnValueFromAccount" access="public" returntype="string" > 
    <cfargument name="accountName" type="string" required="yes" /> 
    <cfargument name="columnName" type="string" required="yes" /> 

    <cfquery name="getColumn" datasource="mydatasource"> 
     SELECT #columnName# 
     FROM table_name 
     WHERE (accountName = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#accountName#'>) 
    </cfquery> 

    <cfreturn getColumn[columnName][1] > 

</cffunction> 

予想通りColumnName機能がadminを返しますよう、アカウントaccountNameExampleSystemadminであると私は関数にrole_ExampleSystemに渡された場合、それが正しくすなわち、指定されたシステムで、アカウントの役割を返します。 。

警告:私のソリューションは、不適切に使用された場合、SQLインジェクションのリスクをもたらす可能性があります。ユーザーがここでcolumnNameのために使用されているデータを入力できるように非常に悪い考えになるように、このようなSQL文でColdFusion変数は、SQLインジェクションから任意の保護を提供していない使用

。私の場合、この関数は私が書いた他のサーバー側関数によってのみ呼び出され、columnNameに使用されるデータはサーバー側の関数でハードコードされます。一方、accountNameはユーザー指定であるため、cfqueryparamにあることが重要です。

アン代替、より安全なソリューション:

マーク・A・クルーガーmentionedちょうどあなたが必要とちょうどあなたが実際に興味を持っているものを読むかもしれないすべての列を選択するために、良いアイデアかもしれないとこれはかなりのように思えます。良いアイデア。結局のところ、レコードのすべての(関連する)列を取得することは、私の単一の列の例よりもはるかに大きなデータベース呼び出しではありません。このようにしてもよいでしょうし、副次的なメリットとして、cfqueryの通常のcoldfusion を使用してSQLインジェクションを心配する必要はありません。

皆の回答とコメントを読むことは非常に啓発的でした。うまくいけば、この質問とその答えは、ColdFusionで同様のことをするのに興味がある他の人に役立ちます。

+2

はい、私は関数を気にしないと言っていました:) Markとしてすべての列を返すほうがずっと簡単です。テーブルに複数のBLOB列が含まれている場合を除き、それは大きな問題です。 – Leigh

+0

合意。帯域幅が今日ではかなり安いので、SQLの戻り値を1つの値にするためのこの作業はまったく無意味です。 – Ectropy

+1

さらに、データベースはおそらく、異なる列を選択する一連の異なるステートメントよりも効果的に実行計画をキャッシュします。特にcfqueryparamを使用している場合。 – Leigh

3

クエリは、queryname [key] [1]のように配列の構造体です。

これは下位互換性のために最初のインスタンスで動作します。最初からqueryname.columnnameを実行すると、CFはその列のクエリの最初の行を出力します。オブジェクト構文に切り替えると、それはもはやそのように機能しません。

はあなたのcfreturnでこれを試してみてください:

getColumn[columnName][1] 

注 - あなたはあなたのcfreturn例のシャープ記号を必要としません。

+0

このメソッドは、 'columnName'' cfqueryparam'を変更し、 '#column## 'のような通常のcoldfusion変数に置き換えた後に機能しました。 – Ectropy

+0

ええ、あなたのコードでその問題を確認できませんでした。 cfqueryparamは変数をプリミティブ型にバインドするため、カラム名として使用することはできません。 –

+2

ちょっと覚えておいてください。このようにクエリのcolumnameを使用すると、SQLインジェクションまで開くことができます(クエリに直接使用される文字列を動的に渡すことができるため)。したがって、USER入力をその関数に渡さないようにしてください。実際には、とにかくすべての列を選択しないようにする理由はありませんし、あなたのcfreturnはあなたが返すものを並べ替えることができますか? –

関連する問題