jueves, junio 12, 2008

Acceso a MSSQL desde Python / PHP


Sistemas operativos: Linux y Windows

Notas y posible apunte de alumnos

Comic: http://the-geek.org/xkcd-es/strips/python/



Comprobado en MSSQL 2000 Enterprise en ingles, con SP2 (en inglés también). La versión en español presentaba problemas aleatorios de acceso al puerto 1433, y no traía la simpática base Northwind.

Notas importantes

Importación de base anterior, en MySQL:
  • http://www.microsoft.com/technet/prodtechnol/sql/2000/deploy/mysql.mspx

Codificación

El primer cabezazo serio trabajando con Python/PHP y contra MSSQL, sobre Windows / Linux / BSD, seguramente serán las codificaciones. En términos generales:

(Fixme):
  • Las ventanas trabajan en UTF-8
  • Las consolas Linux (actuales), en UTF-8
  • Las consolas BSD, en ISO8859
  • MSDOS, en ASCII
  • Las bases de datos, en ISOnnnnn o tambien, latin1

He dejado varios vínculos útiles en http://del.icio.us/karancho/utf-8

#Ejemplo con datos de MSSQL, base Northwind
print unicode(oRS.Fields.Item("ShipAddress"))

#Ejemplo decodeando un valor dentro de un array, procedente de MySQL, via ADODB, en
#latin1 (ISO8859-15, creo), y repleto de acentos y caracteres raros
print arreglo['curso'].decode('latin1')

#Ejemplo para cargar un wx.grid, en una posición determinada
nombre = arr['nombre'].decode('latin1')
grid.SetCellValue(i, 2, nombre)

Mapa

MSSQL Desde Linux
Dentro de Windows
Python
Ejemplo 2
Ejemplo 3
PHP
Ejemplo 1
Idem Ejemplo 1



Ejemplo 1: Cliente: Linux
+ PHP
-> Destino: Windows con MSSQL


  • Paquetes necesarios en Ubuntu: php5-adodb y php5-sybase
  • En Windows, con los componentes ADODB que trae XAMPP es suficiente.
  • ¡No copiar código desde aquí!, hacerlo desde http://pastebin.lugmen.org.ar/4164


<?php
print "
<HEAD>
<!-- <meta http-equiv='Content-Type' content='text/html; charset=utf-8'/> -->

<!-- Codificaciones debido a los acentos procedentes de SQL Server -->
<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'/>
<!-- <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/> -->

</HEAD>
";


$resource=mssql_connect("192.168.1.151","sa","coso");
mssql_select_db("Northwind",$resource);

$sql="SELECT * FROM Orders";

$respuesta=mssql_query($sql,$resource);

while ($fila = mssql_fetch_object($respuesta) ) echo "<p>".$fila->ShipCity;

?>


Ejemplo 2: Cliente: Linux + Python-> Destino: Windows con MSSQL


Ejemplo y configuración:

  • http://pymssql.sourceforge.net/example_pymssql.html

Editores: SPE, Geany, Gvim

Ejemplo de Código

import pymssql

con = pymssql.connect(host='192.168.1.151',user='sa',
password='coso',database='Northwind')

cur = con.cursor()

query="select * from Orders;"
for x in range(10):
cur.execute(query)

while 1:
print "n"
print cur.fetchall()
if 0 == cur.nextset():
break


Ejemplo 3: Computadora corriendo Windows + Python + MSSQL
(con ADO)



  • Python for Windows Extensions: http://starship.python.net/crew/mhammond/
  • Aunque yo usé: http://sourceforge.net/projects/pywin32/
  • Estas pruebas las he realizado con MSSQL 2000. Con MSSQL 2005, al poderse usar ODBC sobre SQL server, hay una manera mas simple, documentada en http://www.time-travellers.org/shane/howtos/MS-SQL-Express-Python-HOWTO.html
  • Ejemplo y configuración: http://www.mayukhbose.com/python/ado/ado-python.php

Ejemplo de Código

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# First import two useful modules
from win32com.client import Dispatch
from adoconstants import *

# Create the ADO Connection object via COM.
oConn = Dispatch('ADODB.Connection')

# Now set the connection properties via the ConnectionString
# We're connecting to a SQL Server on 192.168.1.100 using OLEDB.
oConn.ConnectionString = "Provider=SQLOLEDB.1;Data Source=OREGANOOREGANO;" + "uid=sa;pwd=coso;database=Northwind"

oConn.Open()

# Now create a RecordSet object and open a table
oRS = Dispatch('ADODB.RecordSet')
oRS.ActiveConnection = oConn # Set the recordset to connect thru oConn
oRS.Open("Orders")

#print oRS.Fields.Item(0), oRS.Fields(1)

while not oRS.EOF:
#El siguiente print requiere de convertir los datos procedentes de SQL, en ISO, hacia unicode
#Se agradece el comentario de :
http://sebsauvage.net/python/snyppets/#unicode
print unicode(oRS.Fields.Item("ShipAddress"))
oRS.MoveNext()


Espero que sirva :)


4 comentarios:

Unknown dijo...

Codificaciones debido a los acentos procedentes de SQL Server
meta http-equiv='Content-Type' content='text/html; charset=win dows-1252'/
meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/


No puedes usar acaso utf-8 y cambiar la collation del sql??

pancutan dijo...

Si. En MySQL, donde el procedimiento habitual sería:
- Cambiar la collation a utf-8
- Dumpear la base a un archivo.sql,
- Hacerle un iconv al archivo
- Restaurarla

Sin embargo, en MSSQL 2000 no he encontrado ninguna opción para cambiar la codificación de los datos.

Salu2!

pancutan dijo...

Puertos y Firewalls

En ocasiones MSSQL 2000 no bindea bien los puertos al exterior. Algunos trucos que me funcionaron:

- Usar MSSQL 2000 en ingles, agregando al menos el Servipack 2 (de MSSQL)

- Entrar a Conexiones de Red → red de Area local → Propiedades → Avanzadas → Proteger mi equipo … → Avanzadas

- Agregar los puertos 1433, 1434, 1159, 135, 137 al 139, todos tanto por UDP como por TCP.

Un poco bestia pero al menos ya no tendremos problemas accediendo desde el Linux.

pancutan dijo...

Actualización: el pastebin de lugmen me borro la entrada del ejemplo en PHP. Para evitar errores al copiar/pegar, háganlo desde aquí: http://pastie.textmate.org/560956