mysql經常使用操做彙總

本文已經遷移至:java

https://bitbucket.org/xurongzhong/testing/wiki/mysql%E5%B8%B8%E7%94%A8%E6%93%8D%E4%BD%9C%E6%B1%87%E6%80%BBpython

 

 

 

高可用mysql 的python代碼:mysql

 

https://launchpad.net/mysql-replicant-pythongit

 

Mysql API

 

mysql python api

Mysql 在python有不少鏈接庫。目前用戶最多的要數:https://pypi.python.org/pypi/MySQL-python。它還有一個精煉版本:https://github.com/farcepest/moist。可是近期更新比較慢,不支持python3。尤爲oracle的官方的mysql-connector-python鏈接器逐漸成熟以後,參見:http://dev.mysql.com/doc/connector-python/en/。github

初期mysql-connector-python處理中文等不夠完美,可是逐漸完善,並增長了c語言實現版本,性能大幅度提升。對python3支持也比較好。可是常常經過pip install的方式沒法安裝,此時就須要克隆https://github.com/mysql/mysql-connector-python.git,用python setup.py install的方式安裝。sql

import mysql.connector

try:
  conn_params = {
    "database": "cookbook",
    "host": "localhost",
    "user": "cbuser",
    "password": "cbpass",
    "charset": "utf8",
  }
  conn = mysql.connector.connect(**conn_params)
  print("Connected")
except:
  print("Cannot connect to server")
else:
  conn.close()
  print("Disconnected")

常見選項:數據庫

conn_params = {
    "database": "cookbook",
    "host": "localhost",
    "port": 3307,
    "unix_socket": "/var/tmp/mysql.sock",    
    "user": "cbuser",
    "password": "cbpass",
  }

mysql java api

基於jdbc,使用MySQL Connector/J。api

// Connect.java: connect to the MySQL server

import java.sql.*;

public class Connect
{
  public static void main (String[] args)
  {
    Connection conn = null;
    String url = "jdbc:mysql://localhost/cookbook";
    String userName = "cbuser";
    String password = "cbpass";

    try
    {
      Class.forName ("com.mysql.jdbc.Driver").newInstance ();
      conn = DriverManager.getConnection (url, userName, password);
      System.out.println ("Connected");
    }
    catch (Exception e)
    {
      System.err.println ("Cannot connect to server");
      System.exit (1);
    }
    if (conn != null)
    {
      try
      {
        conn.close ();
        System.out.println ("Disconnected");
      }
      catch (Exception e) { /* ignore close errors */ }
    }
  }
}

能夠省略主機,默認爲localhost,好比jdbc:mysql:///。
其餘方式:String url = "jdbc:mysql://localhost/cookbook?user=cbuser&password=cbpass";
Connector/J 不支持Unix domain socket,指定端口:String url = "jdbc:mysql://127.0.0.1:3307/cookbook";oracle

錯誤處理

錯誤發生時,mysql提供:app

  • 錯誤號
  • 錯誤信息
  • SQLSTATE,5個字符的錯誤碼,基於 ANSI和ODBC標準。

另外查詢和ERROR日誌也有輔助做用。

python

#!/usr/bin/python
# error.py: demonstrate MySQL error handling

import mysql.connector
import sys

#@ _FRAG_
conn_params = {
  "database": "cookbook",
  "host": "localhost",
  "user": "baduser",
  "password": "badpass"
}

try:
  conn = mysql.connector.connect(**conn_params)
  print("Connected")
except mysql.connector.Error as e:
  print("Cannot connect to server")
  print("Error code: %s" % e.errno)
  print("Error message: %s" % e.msg)
  print("Error SQLSTATE: %s" % e.sqlstate)
  for  item in sys.exc_info():
    print item
  
#@ _FRAG_
else:
  conn.close()
  print("Disconnected")

執行會發現e.errno、e.msg、e.sqlstate等比sys.exc_info()要更可讀,不過注意不是python的全部異常都有這些字段。

Java中簡單的異常處理以下

try
{
/* ... some database operation ... */
}
catch (Exception e)
{
e.printStackTrace ();
}

不過這樣可讀性不太好。

import java.sql.*;

public class Error
{
  public static void main (String[] args)
  {
    Connection conn = null;
    String url = "jdbc:mysql://localhost/cookbook";
    String userName = "baduser";
    String password = "badpass";

    try
    {
      Class.forName ("com.mysql.jdbc.Driver").newInstance ();
      conn = DriverManager.getConnection (url, userName, password);
      System.out.println ("Connected");
      tryQuery (conn);    // issue a query
    }
    catch (Exception e)
    {
      System.err.println ("Cannot connect to server");
      System.err.println (e);
      if (e instanceof SQLException)  // JDBC-specific exception?
      {
        // e must be cast from Exception to SQLException to
        // access the SQLException-specific methods
        printException ((SQLException) e);
      }
    }
    finally
    {
      if (conn != null)
      {
        try
        {
          conn.close ();
          System.out.println ("Disconnected");
        }
        catch (SQLException e)
        {
          printException (e);
        }
      }
    }
  }

  public static void tryQuery (Connection conn)
  {
    try
    {
      // issue a simple query
      Statement s = conn.createStatement ();
      s.execute ("USE cookbook");
      s.close ();

      // print any accumulated warnings
      SQLWarning w = conn.getWarnings ();
      while (w != null)
      {
        System.err.println ("SQLWarning: " + w.getMessage ());
        System.err.println ("SQLState: " + w.getSQLState ());
        System.err.println ("Vendor code: " + w.getErrorCode ());
        w = w.getNextWarning ();
      }
    }
    catch (SQLException e)
    {
      printException (e);
    }
  }

  public static void printException (SQLException e)
  {
    // print general message, plus any database-specific message
    System.err.println ("SQLException: " + e.getMessage ());
    System.err.println ("SQLState: " + e.getSQLState ());
    System.err.println ("Vendor code: " + e.getErrorCode ());
  }
}

封裝庫

爲了方便,咱們對數據庫鏈接進行了簡單的封裝:

cookbook.py

import mysql.connector

conn_params = {
  "database": "cookbook",
  "host": "localhost",
  "user": "cbuser",
  "password": "cbpass",
}

# Establish a connection to the cookbook database, returning a connection
# object.  Raise an exception if the connection cannot be established.

def connect():
  return mysql.connector.connect(**conn_params)

使用:harness.py

import mysql.connector
import cookbook

try:
  conn = cookbook.connect()
  print("Connected")
except mysql.connector.Error as e:
  print("Cannot connect to server")
  print("Error code: %s" % e.errno)
  print("Error message: %s" % e.msg)
else:
  conn.close()
  print("Disconnected")
package com.kitebird.mcb;

import java.sql.*;
import java.util.*;  

public class Cookbook
{

  public static Connection connect () throws Exception
  {
    String url = "jdbc:mysql://localhost/cookbook";
    String user = "cbuser";
    String password = "cbpass";

    Class.forName ("com.mysql.jdbc.Driver").newInstance ();
    return (DriverManager.getConnection (url, user, password));
  }

  public static Connection propsConnect () throws Exception
  {
    String propsFile = "Cookbook.properties";
    Properties props = new Properties ();
    String host = "";
    String database = "";
    String user = "";
    String password = "";

    props.load (Cookbook.class.getResourceAsStream (propsFile));
    host = props.getProperty ("host", "localhost");
    database = props.getProperty ("database", "cookbook");
    user = props.getProperty ("user", "");
    password = props.getProperty ("password", "");

    String url = "jdbc:mysql://" + host + "/" + database;
    Class.forName ("com.mysql.jdbc.Driver").newInstance ();
    return (DriverManager.getConnection (url, user, password));
  }


  public static String getErrorMessage (Exception e)
  {
    StringBuffer s = new StringBuffer ();
    if (e instanceof SQLException)  // JDBC-specific exception?
    {
      // print general message, plus any database-specific message
      s.append ("Error message: " + e.getMessage () + "\n");
      s.append ("Error code: " + ((SQLException) e).getErrorCode () + "\n");
    }
    else
    {
      s.append (e + "\n");
    }
    return (s.toString ());
  }


  public static void printErrorMessage (Exception e)
  {
    System.err.println (Cookbook.getErrorMessage (e));
  }
}

使用:

import java.sql.*;
import com.kitebird.mcb.Cookbook;


public class Harness
{
  public static void main (String[] args)
  {
    Connection conn = null;
    try
    {
      conn = Cookbook.connect ();
      System.out.println ("Connected");
    }
    catch (Exception e)
    {
      Cookbook.printErrorMessage (e);
      System.exit (1);
    }
    finally
    {
      if (conn != null)
      {
        try
        {
          conn.close ();
          System.out.println ("Disconnected");
        }
        catch (Exception e)
        {
          String err = Cookbook.getErrorMessage (e);
          System.out.println (err);
        }
      }
    }
  }
}

 

執行語句並獲取結果

SQL語句有些是獲取信息,有些是改變信息。

1,改變信息,不返回信息:INSERT , DELETE ,  UPDATE等
2,不改變信息,不返回信息:好比USE
3,返回信息:SELECT , SHOW , EXPLAIN或DESCRIBE

python操做mysql的演示:stmt.py:

#!/usr/bin/python
# stmt.py: demonstrate statement processing in Python
# (without placeholders)

import sys
import mysql.connector
import cookbook

try:
  conn = cookbook.connect()
except mysql.connector.Error as e:
  print("Cannot connect to server")
  print("Error code: %s" % e.errno)
  print("Error message: %s" % e.msg)
  sys.exit(1)

print("Fetch rows with fetchone")
try:
#@ _FETCHONE_
  cursor = conn.cursor()
  cursor.execute("SELECT id, name, cats FROM profile")
  while True:
    row = cursor.fetchone()
    if row is None:
      break
    print("id: %s, name: %s, cats: %s" % (row[0], row[1], row[2]))
  print("Number of rows returned: %d" % cursor.rowcount)
  cursor.close()
#@ _FETCHONE_
except mysql.connector.Error as e:
  print("Oops, the statement failed")
  print("Error: %s" % e)

# Note: Following loop would be shorter if written like this:
#  for row in cursor:
# But don't do that because surrounding text in book discusses how to
# use rows as a direct-access array following the fetch operation.

print("Fetch rows with fetchall")
try:
#@ _FETCHALL_
  cursor = conn.cursor()
  cursor.execute("SELECT id, name, cats FROM profile")
  rows = cursor.fetchall()
  for row in rows:
    print("id: %s, name: %s, cats: %s" % (row[0], row[1], row[2]))
  print("Number of rows returned: %d" % cursor.rowcount)
  cursor.close()
#@ _FETCHALL_
except mysql.connector.Error as e:
  print("Oops, the statement failed")
  print("Error: %s" % e)

print("Fetch rows using cursor as iterator")
try:
#@ _CURSOR_ITERATOR_
  cursor = conn.cursor()
  cursor.execute("SELECT id, name, cats FROM profile")
  for (id, name, cats) in cursor:
    print("id: %s, name: %s, cats: %s" % (id, name, cats))
  print("Number of rows returned: %d" % cursor.rowcount)
  cursor.close()
#@ _CURSOR_ITERATOR_
except mysql.connector.Error as e:
  print("Oops, the statement failed")
  print("Error: %s" % e)

print("Execute UPDATE statement (no placeholders)")
try:
#@ _DO_1_
  cursor = conn.cursor()
  cursor.execute("UPDATE profile SET cats = cats+1 WHERE name = 'Sybil'")
  print("Number of rows updated: %d" % cursor.rowcount)
  cursor.close()
  conn.commit()
#@ _DO_1_
except mysql.connector.Error as e:
  print("Oops, the statement failed")
  print("Error: %s" % e)

conn.close()

執行結果:

$ python stmt.py 
Fetch rows with fetchone
id: 1, name: Sybil, cats: 1
id: 2, name: Nancy, cats: 3
id: 3, name: Ralph, cats: 4
id: 4, name: Lothair, cats: 5
id: 5, name: Henry, cats: 1
id: 6, name: Aaron, cats: 1
id: 7, name: Joanna, cats: 0
id: 8, name: Stephen, cats: 0
Number of rows returned: 8
Fetch rows with fetchall
id: 1, name: Sybil, cats: 1
id: 2, name: Nancy, cats: 3
id: 3, name: Ralph, cats: 4
id: 4, name: Lothair, cats: 5
id: 5, name: Henry, cats: 1
id: 6, name: Aaron, cats: 1
id: 7, name: Joanna, cats: 0
id: 8, name: Stephen, cats: 0
Number of rows returned: 8
Fetch rows using cursor as iterator
id: 1, name: Sybil, cats: 1
id: 2, name: Nancy, cats: 3
id: 3, name: Ralph, cats: 4
id: 4, name: Lothair, cats: 5
id: 5, name: Henry, cats: 1
id: 6, name: Aaron, cats: 1
id: 7, name: Joanna, cats: 0
id: 8, name: Stephen, cats: 0
Number of rows returned: 8
Execute UPDATE statement (no placeholders)
Number of rows updated: 1

注意:除了fetchall方法以後,其餘都只能往前,不能日後。不過使用fetchall注意不要把內存塞滿了。

語句中的特殊字符和NULL值

引號、反斜槓及NULL,另外還有防止SQL注入攻擊。可使用佔位符或引用函數。好比:

INSERT INTO profile (name,birth,color,foods,cats)
VALUES('De'Mont','1973-01-12','blue','eggroll',4);

INSERT INTO profile (name,birth,color,foods,cats)
VALUES('De''Mont','1973-01-12','blue','eggroll',4);

INSERT INTO profile (name,birth,color,foods,cats)
VALUES('De\'Mont','1973-01-12','blue','eggroll',4);

在沒有開啓ANSI_QUOTES SQL的狀況下:
INSERT INTO profile (name,birth,color,foods,cats)
VALUES("De'Mont",'1973-01-12','blue','eggroll',4);

INSERT INTO profile (name,birth,color,foods,cats)
VALUES('De''Mont','1973-01-12',NULL,'eggroll',4);


INSERT INTO profile (name,birth,color,foods,cats)
VALUES(?,?,?,?,?)
INSERT INTO profile (name,birth,color,foods,cats)
VALUES(%s,%s,%s,%s,%s)

Python種用%s表示佔位符,原始%用%%表示。

#!/usr/bin/python

import mysql.connector
import cookbook

conn = cookbook.connect()

try:
#@ _FETCHLOOP_
  cursor = conn.cursor()
  cursor.execute("SELECT name, birth, foods FROM profile")
  for row in cursor:
    row = list(row)  # convert nonmutable tuple to mutable list
    for i, value in enumerate(row):
      if value is None:  # is the column value NULL?
        row[i] = "NULL"
    print("name: %s, birth: %s, foods: %s" % (row[0], row[1], row[2]))
  cursor.close()
#@ _FETCHLOOP_
except mysql.connector.Error as e:
  print("Oops, the statement failed")
  print("Error: %s" % e)

conn.close()

更加推薦的格式以下:

#!/usr/bin/python

import mysql.connector
import cookbook

conn = cookbook.connect()

try:
#@ _FETCHLOOP_
  cursor = conn.cursor()
  cursor.execute("SELECT name, birth, foods FROM profile")
  for row in cursor:
    row = list(row)  # convert nonmutable tuple to mutable list
    for i, value in enumerate(row):
      if value is None:  # is the column value NULL?
        row[i] = "NULL"
    print("name: {0}, birth: {1}, foods: {2}".format(row[0], row[1], row[2]))
  cursor.close()
#@ _FETCHLOOP_
except mysql.connector.Error as e:
  print("Oops, the statement failed")
  print("Error: {0}".format(e))

conn.close()
相關文章
相關標籤/搜索