PHP pg_query_params

(PHP 5>= 5.1.0, PHP 7)

pg_query_params - Изпраща параметризирана заявка към сървъра, параметрите се предават отделно от текста на SQL заявката

Изпраща параметризирана заявка до сървъра и изчаква резултата. Параметрите се предават отделно от низа на заявката.

pg_query_params() е подобен на pg_query() , но предоставя допълнителна функционалност: параметрите на заявката могат да се предават отделно от низа на заявката.pg_query_params() се поддържа при връзки към PostgreSQL сървъри версия 7.4 и по-нова. Функцията няма да работи с по-стари сървъри.

Ако се използват параметри, те заместват псевдопроменливите $1, $2 и т.н. в низа на заявката. Един и същ параметър може да бъде зададен повече от веднъж в заявка; в този случай ще се използват същите стойности. params дефинират текущите стойности на параметрите. СтойносттаNULL в масива от параметри ще означава SQL NULL в заявката.

Основното предимство наpg_query_params() пред pg_query() е, че стойностите на параметрите могат да се предават отделно от низа на заявката. Това избягва досадната и податлива на грешки процедура на избягване на специални символи и цитиране на стойности. Въпреки това, за разлика от pg_query(), тази функция поддържа само една SQL заявка на подаден низ. (Може да съдържа точка и запетая, но не повече от един непразен SQL оператор.)

Списък с параметри

Ресурс за свързване на PostgreSQL база данни. Ако параметърът за връзка не е посочен, ще се използва връзката по подразбиране, последната връзка, отворена от pg_connect() или pg_pconnect().

Параметризирана SQL заявка. Трябва да съдържа само един израз (множество изразиточки и запетая не се поддържат). Ако към заявката се подадат параметри, те ще заменят псевдопроменливите $1, $2 и т.н.

Потребителските данни винаги трябва да се предават като параметри, а не директно към низа на заявката, където това може да доведе до възможни атаки чрез SQL инжектиране и да причини грешки, ако данните съдържат кавички. Ако по някаква причина не можете да използвате параметър, уверете се, че потребителските данни са правилно екранирани.

Масив от стойности на параметри на заявка за замяна на псевдопроменливи $1, $2 и т.н. в оригиналния низ на заявката. Броят на елементите на масива трябва точно да съвпада с броя на псевдопроменливите.

Стойностите, предназначени за полета bytea, не могат да бъдат предавани като параметри. Използвайте функцията pg_escape_bytea() или функциите за големи обекти.

Върнати стойности

Ресурс за резултат от заявка илиFALSE, ако е възникнала грешка.

Пример #1 Пример за използванеpg_query_params()

// Свързване към база данни "mary" $dbconn = pg_connect ( "dbname=mary" );

// Намерете всички магазини с име „Joe's Widgets“. Обърнете внимание, че няма нужда да избягвате // специалните символи в низа "Joe's Widgets" $result = pg_query_params ( $dbconn , 'SELECT * FROM shops WHERE name = $1' , array( "Joe's Widgets" ));

// Същото за сравнение, използвайки функцията pg_query $str = pg_escape_string ( "Джаджи на Джо"); $result = pg_query ( $dbconn , "SELECT * FROM shops WHERE name = ' < $str >'" );

Вижте също

Допринесени от потребителя бележки 15 бележки

Ако трябва да предоставите множество възможни стойности за поле в заявка за избор, следното ще ви помогне.

// Да приемем, че $values[] е anмасив, съдържащ стойностите, които ви интересуват. $values ​​= array( 1 , 4 , 5 , 8 );

// За да изберете променлив брой аргументи с помощта на pg_query(), можете да използвате: $valuelist = implode ( ', ' , $values ​​); $query = "SELECT * FROM table1 WHERE col1 IN ( $valuelist)" ; $result = pg_query ( $query ) or die( pg_last_error ());

// Вместо това трябва да използвате следния подход: $valuelist = '' $query = 'SELECT * FROM table1 WHERE col1 = ANY ($1)' ; $result = pg_query_params ($query, array($valuelist)); ?> Грешката, получена в този пример, е генерирана от PostGreSQL.

Последният метод работи чрез създаване на SQL масив, съдържащ желаните стойности. 'IN (. )' и ' = ANY (. )' са еквивалентни, но ANY е за работа с масиви, а IN е за работа с прости списъци.

Не можете да изпълнявате множество изрази с pg_query_params, но все пак можете да имате поддръжка на транзакции, без да се връщате към pg_query:

= pg_connect ( "host=127.0.0.1 port=5432 dbname=foo user=bar password=baz" ); pg_query ($connection, 'ПУСКА ТАБЛИЦА, АКО СЪЩЕСТВУВА пример'); pg_query ( $connection , 'CREATE TABLE example (col char(1))' ); pg_query ( $connection , 'INSERT INTO example (col) VALUES (\'a\')' ); // 'SELECT col FROM example' в друга сесия връща "a" pg_query ( $connection , 'BEGIN' ); pg_query_params ($connection, 'UPDATE example SET col = $1', array('b')); // 'SELECT col FROM example' в друга сесия все още връща "a" pg_query_params ( $connection, 'UPDATE example SET col = $1', array( 'c' )); // 'SELECT col FROM example' в друга сесия все още връща "a" pg_query ( $connection , 'COMMIT' ); // 'SELECT col FROM example' в друга сесия връща "c" ?>

pg_query иpg_query_params може да се комбинира в една функция. Това също премахва необходимостта от конструиране на масив от параметри за pg_query_params:

функция my_query ($conn, $query) < if( func_num_args () == 2 ) връща pg_query ($conn, $query);

$args = func_get_args (); $params = array_splice ($args, 2); върни pg_query_params ($conn, $query, $params); > ?> Употреба:

/* непараметризиран пример */ my_query ( $conn , "SELECT $val1 + $val2 " );

/* параметризиран пример */ my_query ( $conn , "SELECT $1 + $2" , $val1 , $val2 ); ?>

= ". "; $params = масив (1, 2, 3, вярно, невярно);

//Сега направете заявката: $result = pg_query_params ( $sql , $params ); $row = pg_fetch_assoc ( $result , 0 ) //първи ред

//За булеви стойности, конвертирайте 't' и 'f' обратно в true и false. Проверете типа на колоната, за да не преобразуваме случайно грешното нещо. foreach ( $row as $key => & $value ) < $type = pg_field_type ($result, pg_field_num ($result, $key)); if ( $type == 'bool' ) $value = ( $value == 't' ); > >

//$row[] вече съдържа булеви стойности, NULLS и низове. ?>

Що се отнася до булевите стойности, просто ги преобразувайте като (цяло число), когато ги предавате в заявката си - '0' и '1' са напълно приемливи литерали за SQL булев вход:

Също така е безопасно да напишете вашата параметризирана заявка в двойни кавички, което ви позволява да смесвате постоянни стойности и контейнери във вашата заявка, без да се налага да се притеснявате как дали PHP ще се опита да замени променливи във вашия параметризиран низ.

Разбира се, това също означава, че за разлика от синтаксиса на низ с двойни кавички на PHP, вие МОЖЕТЕ да включите литерал $1, $2 и т.н. в SQL низове, напр.

//Работи ($1 е контейнер, $2 се означава буквално) pg_query_params ( "INSERT INTO foo (col1, col2) VALUES ($1, 'costs $2')" , Array( $data1 ));

// Извежда E_WARNING (подава твърде много параметри) pg_query_params ( "INSERT INTO foo (col1, col2) VALUES ($1, 'costs $2')" , Array( $data1 , $data2 )); ?>

Когато вмъквате в pg колона от тип bool, не можете да предоставите PHP тип bool. Вместо това трябва да използвате низ "t" или "f". PHP се опитва да промени булеви стойности, предоставени като параметри на низове, и след това се опитва да използва празен низ за false.

Пример за неуспех: pg_query_params('вмъкване в таблица1 (bool_column) стойности ($1)', array(false));

Работи: pg_query_params('вмъкнете в lookup_permissions (системни) стойности ($1)', array(false ? 't' : 'f'));

Ако локалът на вашата система използва "," като десетичен разделител, следното ще доведе до грешка в базата данни:

pg_query_params($conn, 'SELECT $1::numeric', array(3.5));

За да работи това, е необходимо ръчно да конвертирате 3.5 в низ, като използвате напр. номер_формат.

(Записах това като грешка #46408, но очевидно е очаквано поведение.)

Ако се опитвате да копирате функцията pg_query_params, може също да искате да поддържате NULL стойности. Докато is_int връща true за NULL стойност, форматирането за SQL.

функция pg_query_params( $db, $query, $parameters ) // Ескейп параметри според изискванията & параметри за изграждане на функция за обратно извикване глобални $pg_query_params__parameters; foreach( $parameters as $k=>$v ) if ( is_null($v) ) $parameters[$k] = 'NULL'; > else $parameters[$k] = ( is_int( $v ) ? $v : "'".pg_escape_string( $v)."'" ); > > $pg_query_params__parameters = $параметри;

// Извикване чрез pg_query returnpg_query( $db, preg_replace_callback( '/\$([0-9]+)/', 'pg_query_params__callback', $query)); >

Това е полезна функция за предотвратяване на атаки чрез SQL инжектиране, така че за тези от нас, които все още не могат да надстроят до PHP5.1, ето заместваща функция, която работи по подобен начин на по-стари версии на PHP.

# Параметризирана реализация на заявка за Postgresql и по-стари версии на PHP

if( ! function_exists ( 'pg_query_params' ) )

функция pg_query_params__callback ( $at ) глобални $pg_query_params__parameters; връщане на $pg_query_params__parameters [ $at [ 1 ]- 1 ]; >

функция pg_query_params ($db, $query, $parameters)

// Изходни параметри според изискванията & изграждане на параметри за функция за обратно извикване глобални $pg_query_params__parameters; foreach( $parameters as $k => $v ) $parameters [ $k ] = ( is_int ( $v ) ? $v : "'". pg_escape_string ( $v). "'" ); $pg_query_params__parameters = $параметри;

// Обаждане чрез pg_query връщане pg_query ( $db , preg_replace_callback ( '/\$([0-9]+)/' , 'pg_query_params__callback' , $query ) );

// Пример: pg_query_params( $db_resource, "SELECT * FROM table WHERE col1=$1 AND col2=$2", array( 42, "It's ok" ) ); ?>

Ако един от параметрите е масив (напр. масив от int, който се предава на съхранена процедура), той трябва да бъде обозначен като набор в масива, а не като нотация на php масив.

например: var_dump изход от 2 parms едно цяло число и масив от int aaa е: Array ( [0] => 1 [1] => )

не искате:

Отстраняването на грешки в параметризирани заявки може да бъде досадно, ако искате да поставите заявката директно в PSQL. Ето един трик, който помага:

= "ИЗБЕРЕТЕ * от таблицата WHERE col_a = $1 и col_b=$2 и col_c=$3" ; $params = масив (42, "низ", NULL);

$debug = preg_replace_callback ( '/\$(\d+)\b/' , function( $match ) use ( $params ) < $key =( $match [ 1 ]- 1 ); return ( is_null ( $params [ $key ])? 'NULL' : pg_escape_literal ( $params [ $key ]) ); >, $sql );

echo "$debug"; //отпечатва: SELECT * от таблицата WHERE col_a = '42' и col_b='низ' и col_c=NULL ?> Това работи правилно, освен в (необичайния) случай, когато имаме буквално $N; регулярният израз го замества там, където не трябва. Например: //И двете ' . $1. ' и $1 се заменят; първият е грешен, вторият е прав. $sql = "ИЗБЕРЕТЕ 'Вашата сметка е за $1' КАТО фактура WHERE 7 = $1" ; $params = масив(7); //$debug: ИЗБЕРЕТЕ 'Вашата сметка е за $7' КАТО фактура WHERE 7 = '7'" ?>

pg_query_params() *приема* NULL. Те автоматично ще бъдат трансформирани, правилно, в SQL NULL. Така, например:

= "АКТУАЛИЗИРАНЕ tbl_example SET column_a = $1, column_b=$2" ; $params = масив(NULL, 42); $result = pg_params ($sql, $params);

//е еквивалентно на: $result = pg_query ( "UPDATE tbl_example SET column_a = NULL column_b = '42')" ;

//а не, както може да се опасява, някое от тези (неправилни) неща: // . колона_a = ''. // . column_a = 'NULL'. ?> Имайте предвид, че можете да използвате NULL по този начин в израз UPDATE или INSERT, но НЕ и в клауза WHERE. Това не е ограничение на pg_query_params(), а по-скоро е следствие от езика SQL. Така че, ако искате заявка от типа:

= "ИЗБЕРЕТЕ. КЪДЕ колоната НЕ Е РАЗЛИЧНА ОТ $1" $params = масив ( 42 ); //това работи, същото като "където колона = 42" $params = масив ( NULL ); //това работи, същото като "където колоната е нула" ?> (Настрана: въпреки че това е досадно,поведението е правилно. Има опция за съвместимост с postgresql „transform_null_equals“, но тя няма да ви помогне тук, въпреки че може да очаквате.)

За съжаление параметрите няма да зачитат низови представяния на NULL или NOW(). Ако вашият код избутва тези стойности, те се считат за низ и се вмъкват буквално като „NULL“ и „NOW()“.

В идеалния случай трябва да има допълнителен параметър, който можете да присвоите, за да принудите този текст като pgSQL функции/резервирани думи и да не ги увивате като низове (ако приемем, че параметризираните заявки на pgSQL поддържат това.

Същият проблем възниква и за списъци със запетая, използвани в "WHERE колона IN (1,2,3,4)", params третира "1,2,3,4" като низ, а не списък с числа, и го изпълнява също с кавички.

За отстраняване на грешки използвам тази функция за симулиране на параметри, имайте предвид, че това не е 100% точно, то само се опитва да симулира действителния SQL, който създават заявките за параметри.

функция pg_query_params_return_sql ($query, $array) < $query_parsed = $заявка;

за ($a = 0, $b = sizeof ($array); $a $b; $a ++) < if ( is_numeric ( $array [ $a ]) ) < $query_parsed = str_replace (( '$' .( $a + 1 )), str_replace ( "'", "''" , $array [ $a ]), $query_parsed ); > друго < $query_parsed = str_replace (( '$' .( $a + 1 )), "'" . str_replace ( "'" , "''" , $array [ $a ]). "'" , $query_parsed ); > >