Coldfusion - добавление неверного параметра в список - PullRequest
2 голосов
/ 07 марта 2019

Я пытаюсь сделать следующее:

sentence = "some set of words";
words = sentence .split(" "); 
qryWords = new Query();
qryWords .setSQL("
    SELECT    
        [word]

    FROM 
        [word_list]

    WHERE
        [word] IN ( :wordsToCheck )
");

qryWords.addParam( name="wordsToCheck", value = words, CFSQLTYPE="CF_SQL_VARCHAR", list="true" );
qryWordsResult = qryWords.execute();

Я получаю 0 результатов, но без ошибок, где я ожидаю, что будут результаты (и я проверил это, заменивпараметр sql со статической строкой).Странно то, что когда я сбрасываю qryWordsResult, он показывает

SQLPARAMETERS   
array
1   [Ljava.lang.String;@3a4b8277

Но если бы я сделал то же самое, используя теги и <cfqueryparam ..., результирующий дамп будет

SQLPARAMETERS   
array
1   words

Ответы [ 2 ]

3 голосов
/ 07 марта 2019

Поскольку вы используете ColdFusion 10, вы будете ограничены в своих возможностях.Но split() - это функция JAVA, а не CF, поэтому она не создает массив CF вашей разделенной строки.Он создает массив JAVA, который немного отличается.То, что вы хотите сделать, это использовать функции CF для изменения разделителей вашей строки (которые являются "").Я не думаю, что cfqueryparam будет интерпретировать пустые строки как разделители в вашей строке, если вы не укажете это.

Во-вторых, это становится немного странным, когда вы работаете Query().Это будет работать в своем собственном контексте, а не в контексте страницы.Так что, если ваш FROM word_list указывает на объект запроса из ранее на странице, вам нужно будет вставить этот объект запроса в Query() [new Query ( word_list = word_list )].Для будущих читателей, использующих CF11 +, вы можете использовать QueryExecute().

. После изменения разделителей вы можете просто использовать эту переменную в качестве value вашего addParam().Или, что еще лучше, не беспокойтесь об изменении разделителей и просто укажите аргумент separator=" " в вашем addParam().Еще одно замечание об аргументах cfqueryparam и использовании list="true" заключается в том, что в зависимости от вашего типа данных он будет немного волшебен, например, будет заключать в кавычки значения, если это тип varchar.Довольно классные вещи.

В любом случае:

<cfscript>

    /**********SIMULATED TABLE**********/
    word_list = queryNew(
        "id, word",
        "integer, varchar",
        [
          { "id": 1, "word": "notit" } ,
          { "id": 2, "word": "set" } ,
          { "id": 3, "word": "notit" } ,
          { "id": 4, "word": "of" } ,
          { "id": 5, "word": "notit" } ,
          { "id": 6, "word": "notitsome" } ,
          { "id": 7, "word": "notit" } ,
          { "id": 8, "word": "some" } ,
          { "id": 9, "word": "words" }
        ]
    ) ;
    /**********SIMULATED TABLE**********/
    //writeDump(word_list) ;


    sentence = "some set of words";
    words = sentence; //listChangeDelims(sentence, ",", " ") ;  

    /// If using CF11+, use QueryExecute() instead of new Query()    
    qryWords = new Query( word_list = word_list ) ; /// The QoQ object is injected into Query.cfc
      qryWords
        .setSQL("SELECT word FROM word_list WHERE word IN ( :wordsToCheck )") 
        .setDBType("query")   /// Just for Query Of Query. 
        //.setDatasource("myDSN") 
        .addParam( name="wordsToCheck", value=words, CFSQLTYPE="CF_SQL_VARCHAR", list="true", separator=" ") ;

    qryWordsResult = qryWords.execute().getResult() ;


    writeDump(qryWordsResult) ;

</cfscript>

Не удалось сохранить код TryCF.com для сохранения, но вы сможете скопировать / вставить и запустить его.Первая половина этого - просто создание поддельного объекта запроса для выполнения окончательного запроса.Если word_list является фактической таблицей в вашем источнике данных, и это не Query of Query, вы можете игнорировать части, которые относятся к QoQ.Я ввел свой word_list объект запроса в Query(), а все остальное довольно стандартно.Для ваших cfqueryparam или addParam() я добавил аргумент separator=" " для обработки вашей исходной строки с разделителями space вместо запятых.Я не знаю, как вы используете результаты, но это должно дать вам их в формате qryWordsResult.word.

3 голосов
/ 07 марта 2019

Это работает, но использование массива работает в <cfqueryparam ..>, поэтому мне интересно, почему [addParam()] не демонстрирует такое же поведение

Это только появляется для работы.Поскольку cfqueryparam ожидает строку, CF молча преобразует массив в строку (т. Е. Литеральную строку [Ljava.lang.String;@3a4b8277).Поэтому, хотя запрос выполняется успешно, эта строка, очевидно, не будет соответствовать ни одному из значений в столбце «слово».

IMO с использованием QueryExecute () проще, чем Query.cfc.Использование заполнителя ? должно помочь.

Обратите внимание, добавление атрибута «разделитель» для изменения разделителя списка на пробел.

result = queryExecute(
 " SELECT [word] FROM   [word_list] WHERE  [word] IN ( ? )"
 , [ { value="some set of words"
      , cfsqltype="cf_sql_varchar"
      , list=true
      , separator=" " } 
   ]
 , {datasource="YourDataSource"}
);
writeDump( result );    
...