Додаток «Hello MySQL» - статті

Автор:Павло Пушкарьов , paulus (at) sqlinfo (dot) ru

Відразу хочу зробити застереження щодо того, що буде в прикладах, а чого не буде, і чому я пишу саме так, а не інакше:

У всіх прикладах буде вирішуватися те саме просте завдання — вивести рядки таблички mysql.user, відповідні певному імені користувача, що передається додатку з командного рядка. Через те, що ім'я передається користувачем, у всіх прикладах використовується спеціальний код, щоб уникнути ін'єкцій SQL.

У цій статті я розгляну три мови, що інтерпретуються: PHP, Perl і Python, а також три компілювані мови: Java, C і C++.

Hello MySQL з використанням PHP

PHP — одна з найбільш популярних мов, яка підтримується більшістю веб-серверів. Для цього прикладу, однак, я використовуватиму не серверну, а консольну версію PHP (для того, щоб можна було передати параметр із командного рядка).

У PHP використовують або звичайну бібліотеку доступу до MySQL або MySQL. Я використовуватиму другу, тому що вона спілкується з MySQL за новим протоколом і дозволяє, наприклад, отримувати результати зі збережених процедур. Також вона дозволяє використовувати об'єктно-орієнтований інтерфейс, який мені близький за духом.

// Перевірити, чи є аргумент програми if ($ argc != 2 ) die ( "USAGE: $ argv [0] \ n ");

// Підключитися до бази $ mysqli = new mysqli ( "localhost", "root", "", "mysql"); if ( $mysqli -> connect_error ) die ( $mysqli -> connect_error . " \n " ) ;

// Підготувати запит $user = $mysqli -> real_escape_string($argv[1]); if ( ! ( $result = $mysqli -> query ( "SELECT * FROM user WHERE user = '$user'" ) ) ) die ( $mysqli-> error. "\n");

// Вивести дані while ( $row = $result -> fetch_row ( ) ) < print (join("\t", $row). "\n"); > ?>

Потрібно зробити кілька зауважень щодо використання цього коду. По-перше, тут я використовую real_escape_string, який у звичайному коді з mysqli не використовується. У mysqli є чудовий метод prepare(), за допомогою якого можна підготувати вираз і автоматично екранувати введення користувача:

На жаль, цей спосіб не підходить у даному випадку, тому що результуючий підготовлений вираз може віддавати результат тільки у прив'язані змінні (на відміну від використаного нами $result, що дозволяє витягувати рядки масивом), тобто ми повинні заздалегідь знати список стовпців і прив'язати до нього наші змінні PHP. У випадку нашої великої кількості стовпців це не зручно.

По-друге, треба розуміти, що $mysqli->connect_error містила помилку до версії PHP 5.2.9, тому слід використовувати її з обережністю.

Hello MySQL з використанням Perl

Perl – чудова мова для швидкої обробки текстової інформації. Для доступу до баз даних Perl використовує узагальнений інтерфейс DBI.

#! /usr/bin/perl use strict; use DBI;

# Перевірити, чи запустили з параметром die ( "USAGE: $0 \n " ) unless ( @ARGV == 1 ) ;

# Відловлювати помилки в кінці eval < # З'єднатися з базою, увімкнути режим виходу при помилках my $dbh = DBI-> connect ( "DBI:mysql:host=localhost;database=mysql" , "root" , "" , < PrintError =>0 , RaiseError => 1 > ) ;

# Виконати запит my $sth = $dbh -> selectall_arrayref ( "SELECT * FROM user WHERE user=?", undef, $ARGV [0]);

# Вивести дані print(join ("\t", @$_). "\n") foreach (@$sth); > ;

# Якщо сталася помилка, показати її die ("Got error: $@") if ($@);

На відміну від PHP, Perl підтримує повноцінні винятки, які спрощують написання частини коду, що відповідає за обробку помилок. Ну і, звичайно, інтерфейс DBI дозволяє дістати дані навіть масивом, при цьому не обмежуючи використання автоматичного екранування аргументів запиту.

Hello MySQL з використанням Python

Python — сучасна швидка мова сценаріїв, яка має свою бібліотеку для доступу до MySQL. Так само, як і Perl, він підтримує винятки, і тому так само, як і в Perl, код його короткий і читаємо:

#! /usr/bin/env python # encoding: utf8 import sys import MySQLdb

# Перевірити, що запущені з параметром if len (sys. argv)! = 2: print ("USAGE:" + sys. argv [0] + "") sys. exit (-1)

# Обробляти помилки в кінці try : # Підключитися до бази даних conn = MySQLdb. connect ( "localhost", "root", "", "mysql")

# Виконати запит cursor=conn. cursor ( ) cursor. execute ( "SELECT * FROM user WHERE user = %s", (sys. argv [1])) rows = cursor. fetchall ( )

# Вивести результат for row in rows: print ( " \t " . join ( [ str ( col ) for col in row ] ) )

except MySQLdb. Error, e: print ("Got error: %s"% (e. args [1])) sys. exit (-1)

Hello MySQL з використанням Java

Java — повноцінна платформа, що компілюється, підтримує спілкування з MySQL через узагальнений інтерфейс доступу до БД JDBC. Для того, щоб працював приклад, необхідно, щоб на клієнтському комп'ютері було встановлено Connector/J.

importjava.sql.DriverManager; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet;

public class Dump < public static void main (String [] args) < // Перевірити, що програма запущена з аргументом if ( args. length 1 ) < System. out. println ("USAGE: java Dumper"); System. exit (-1); >

// Перевіряти помилки наприкінці try < // Підключитися до бази Connection conn = DriverManager . getConnection ("jdbc:mysql://localhost/mysql?user=root");

// Підготувати та виконати запит PreparedStatement stmt = conn. prepareStatement ( "SELECT * FROM user WHERE user=?"); stmt. setString(1, args[0]); ResultSet rs = stmt. executeQuery();

// Вивести дані int columns = rs. getMetaData(). getColumnCount(); while (rs. next ()) < for ( int i = 1 ; i ) < System. out. print(rs. getString(i) + "\t"); > System. out. println (""); >

> catch (Exception ex) < System. out. println ("Got error:" + ex. getMessage()); > > >

Для того, щоб ця програма запрацювала, потрібно її правильно скомпілювати і правильно запустити. З компіляцією все відбувається прямолінійно: достатньо виконати команду javac Dumper.java, щоб отримати скомпільований байт-код програми Dumper.class. Запуск цього байткоду вимагає явного вказівки шляху до драйвера JDBC MySQL:

Hello MySQL з використанням С

Мова С — одна з найперших компілюваних мов, яка збереглася до наших днів. У ньому немає підтримки винятків, тому, як і на PHP, доводиться кожен виклик обертати в if().

Наступний код люб'язно надано для цієї статтіДаниїлом Каменським, dkamenskiy (at) yandex (dot) ru.

#include #include #include #include

/* Функція виводить помилку MySQL */ void print_error (const char * str) < fprintf (stderr, "ERROR: %s \n", str? str: mysql_error (&mysql)); >

/* Основна функція */ int main ( int argc, char ** argv ) < MYSQL_RES *mysqlres; MYSQL_ROW row; char *query; char *tablename; unsigned rows; unsigned i;

/* Перевірити, що програму запустили з параметром */ if ( argc != 2 ) < fprintf (stderr, "USAGE: %s username \n", argv [0]); return -1; >

/* Підключитися до MySQL з параметрами користувача за умовчанням */ if ( !mysql_real_connect ( &mysql, "localhost" , "root" , "" , "mysql" , 0 , NULL , 0 ) ) < print_error (NULL); return -1; >

/* Обробити параметр, щоб не допустити SQL injection */ tablename = malloc (strlen (argv [1]) * 2 + 1); mysql_real_escape_string (&mysql, tablename, argv [1], strlen (argv [1]));

/* Скласти запит */ query = strdup ("SELECT * FROM mysql.user WHERE user = '"); query = realloc (query, strlen (query) + strlen (tablename) + 2); strcat (query, tablename); strcat (query, "'");

/ * Звільнити виділену під складання запиту пам'ять * / free (query); free (tablename);

/* Прочитати результат запиту */ if ( ! ( mysqlres = mysql_store_result ( &mysql ) ) ) < print_error (NULL); mysql_close (&mysql); return -1; >

/ * Вивести результат запиту на екран * / rows = mysql_num_fields (mysqlres); while ((row = mysql_fetch_row (mysqlres))) < for (i = 0; i) printf ("%s\t", row [i]); printf ("\n"); >

/* Звільнити результат запиту */ mysql_free_result ( mysqlres );

/* Відключитися від MySQL */ mysql_close (&mysql); return 0; >

Написання програм на С - розвага для справжніх програмістів :) Потрібно стежити за всім - починаючи від перевірок помилок і закінчуючи коректним звільненням об'єктів та закриттям всіх з'єднань.

При написанні програм на С можна або робити так, як написано в цьому прикладі, або емулювати try-catch блоки за допомогою оператора goto. Зазвичай цей оператор не рекомендується використовувати, але в даному випадку він може значно скоротити обсяг коду, а головне покращити його читання.

Щоб зробити з тексту цього прикладу додаток, потрібно його скомпілювати. Наприклад, якщо Ви користуєтеся компілятором gcc, потрібно виконати

Hello MySQL з використанням С++

Багато хто вважає, що С++ це розширена версія С. За синтаксисом це майже так. Але С++ зовсім інша ідеологія, яку я постараюся передати.

Донедавна єдиною гарною бібліотекою доступу була Connector/C++, яка працювала повністю наслідуючи JDBC. Наступний приклад використовує для своєї роботи, проте бібліотеку mysql++, яка з'явилася відносно недавно, але написана безпосередньо для С++, а тому куди зручніше.

int main ( int argc, char * argv [ ] ) < using namespace mysqlpp;

// Перевірити, що програму запустили з параметром if (argc! = 2) < std:: cerr "USAGE:" [0] "" endl; return -1; >

// Обробляти всі помилки наприкінці try < // Підключитися до MySQL Connection conn ("mysql", "localhost", "root", "");

//Скласти запит Query query=conn. query(); query "SELECT * FROM mysql.user WHERE user="[1];

// Виконати запит StoreQueryResult res = query. store();

// Вивести результат for ( size_t row = 0 ; row num_rows ( ) ; ++row ) < for ( size_t col = 0 ; col num_fields ( ) ; ++col ) std:: cout [ row ] [ col ] " \ t " ; std:: cout endl; >

Для того, щоб скомпілювати цю програму, я використовую наступну команду:

Висновок