Xpoint
   [напомнить пароль]

Mysql 5 и Unicode

Метки: [без меток]
[арх]
2007-02-12 11:28:13 [обр] Илья[досье]
сообщение промодерировано

Здравствуйте уважаемые.
Я новичок в Perl программировании (да и профиль деятельности другой), столкнулся с проблемой.

Написал скрипт, котоорый будет с телефонной станции забирать некие данные. В данном случае телефонный справочник и складывать в БД

Вот код скрипта

#!/usr/local/bin/perl
use utf8;
use DBI;

$dbh=DBI->connect("dbi:mysql:dbname=new","root","password");
$delstring="DELETE FROM phone";
      $dbh->do($delstring);
open IN , "</home/user/input1";
open OUT, ">/home/user/output";
@file=<IN>;
foreach (@file) {
   
$string=$_;
   if ($string=~m/^"\d+","~.*/){
   
$string=~ tr /(A-Z)/(a-z)/;   
$string=~ tr /q,w,e,r,t,y,u,i,o,p,[,],a,s,d,f,g,h,j,k,l,;,',z,x,c,v,b,n,m,,,./й,ц,у,к,е,н,г,ш,щ,з,х,ъ,ф,ы,в,а,п,р,о,л,д,ж,э,я,ч,с,м,и,т,ь,б,ю/;
$string=~ tr /,/б/;
$string=~ tr /\//\./;
$string=~ tr /"/ /;      
$string=~ tr /~/ /;
if ($string=~/^\s+(\d+)\sб\s+(\D+)(\D\.)\s+(\D\.)/)
   {
   $intnum=$1;
      $name="/u$2 /u$3 /u$4"; 
      
$sqlstring="INSERT INTO phone (incnum, name) VALUES ($intnum, $namе)";

      $dbh->do($sqlstring);
      print OUT "$1 \u$2 \u$3 \u$4 \n";
      #print $sqlstring, "\n";
      #print $name, "\n";
      
      
      }

   }
      }
      
      $dbh->disconnect;

Проблема в том, что отказывается класть русские символы в БД.
В ответ выдаёт вот что:

DBD::mysql::db do failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '&&#65533&&удаев  И. А.)' at line 1 at /home/user/Programing/file.cgi line 32, <IN> line 199.

Кодировка для БД стоит utf8_unicode_ci.

Помогите разобраться в чем собственно проблема?

спустя 20 минут [обр] Роман Чемисов(56/327)[досье]
Илья[досье]
Может это из-за того, что Вы их не квотите?
Кстати, в Вашем случае идеально подходит prepare плюс placeholders...
спустя 14 минут [обр] Илья[досье]

да чуть было не забыл
со станции мне приходит файл вот такого формата

"Extension","Name"
"11001","~BDFYJD B/ B/"
и.т.д
в итоге я делаю из этого

11001 Иванов И.И.

И пытаюсь запихать "11001" в одно поле таблицы (всё ОК) и "Иванов И.И." в другое поле (не выходит)

Роман Чемисов[досье]
Простите, ради Бога, но я писал что не силён... Можно чуть подробнее,о том, почему не получается так как я делаю (если я в эскьюэль запрос вместо $name пишу символы латинскими буквами, то он всё вставляет) и ссылочку где разжеванно про "квотите", "prepare" и "placeholders".

Спасибо

спустя 15 минут [обр] Закиров Руслан(69/341)[досье]

Один раз сделайте:

my $sth = $dbh->prepare("INSERT INTO phone (incnum, name) VALUES (?,?)");

Потом можно несколько раз вызывать:

my $rv = $sth->execute($intnum, $namе);
спустя 17 минут [обр] Илья[досье]
сообщение промодерировано

Закиров Руслан[досье]

ааа ... понял
Просто я сейчас сделал в эскьюэль вместо '$name' 'Привет' и он у меня без проблем отработал а потом написал

#!/usr/local/bin/perl
use utf8;
use DBI;

$dbh=DBI->connect("dbi:mysql:dbname=new","root","password");
$sth=$dbh->prepare("SELECT * FROM phone");
$sth->execute();

while (@r=$sth->fetchrow_array)
{
   foreach (@r)
   {print $_;
   }
}

И он у меня абсолютно нормально выдал то что там лежит...

Ща попробую как Вы сказали.

спустя 10 минут [обр] Роман Чемисов(56/327)[досье]
Илья[досье]
prepare надо делать вне цикла, а execute — в цикле.
спустя 15 минут [обр] Илья[досье]
Закиров Руслан[досье], Роман Чемисов[досье]
всё получилось. Спасибо, товарищи. :)
но все же хочется узнать, почему не получалось так как я делал?
спустя 19 минут [обр] Алексей В. Иванов(100/2861)[досье]
Илья[досье] не в тему, но FYI — в операторе tr не нужны скобки и запятые для перечисления. Правильно писать: tr/A-Z/a-z/ и tr/QWE/ЙЦУ/
спустя 2 минуты [обр] Закиров Руслан(69/341)[досье]

Илья[досье] В SQL нужно строковые константы обрамлять в кавычки и если внутри строки есть кавычки, то нужно их защитить спец. символом, например SET field = "my \"value\"". Чтобы не писать эту процедуру самому в DBI у каждого драйвера DB есть метод quote, который принимает строку и ее обрамляет в кавычки согласно требованиям данной БД. Соответственно нужно делать так my $protected_str = $dbh->quote($str);. Вот такую строчку можно уже вставлять непосредственно в текст запроса.

Чтобы еще упростить жизнь программисту в DBI при использовании placeholder'ов защита(quoting, квотирование) выполняется автоматически. И можно написать так:
$dbh->do("SELECT ... WHERE X = ?", {}, 'my "value"');

спустя 13 минут [обр] Илья[досье]

Алексей В. Иванов[досье]

Ну я же говорю... только начал... Спасибо за уточнение.

Закиров Руслан[досье]

Огромное спасибо. Теперь всё ясно. Даже не знаю как и благодарить за такой развёрнутый ответ.

Powered by POEM™ Engine Copyright © 2002-2005