6
import fdb

ruta = 'ale.fdb'

try:
    con = fdb.connect(
    dsn = ruta,
    user = 'sysdba',
    password = '*******',
    charset = 'utf-8'
    )
    print('Conectado !!')
    print('**************************************************')
except:
    print('Fallo la conexion', ruta)

# ********************************************

cx = con.cursor()
sql2 = '''
CREATE TABLE RUBY (
  Id BIGINT NOT NULL PRIMARY KEY,
  nombre VARCHAR(60) CHARACTER SET UTF8 NOT NULL,
  correo VARCHAR(60) CHARACTER SET UTF8 NOT NULL UNIQUE,
  pais VARCHAR(60) CHARACTER SET UTF8 NOT NULL,
  contra VARCHAR(60) CHARACTER SET UTF8 NOT NULL
  );

CREATE GENERATOR gen_ruby_id;
SET GENERATOR gen_ruby_id TO 0;

CREATE TRIGGER BI_RUBY_ID FOR RUBY
ACTIVE BEFORE INSERT
POSITION 0
AS
BEGIN
if (NEW.id is NULL) THEN NEW.id = GEN_ID(gen_ruby_id, 1);
END

'''


cx.execute(sql2)

con.commit()
con.close()

print('Tabla creada !!!')
input()

Lo pregunto porque me sale error de sintaxis, o sea, que algo no está bien escrito. Este es el error:

Traceback (most recent call last):
  File "C:\Users\Beto\Documents\Proyectos python\Ruby\fire.py", line 55, in <module>
    cx.execute(sql2)
  File "C:\Users\Beto\AppData\Local\Programs\Python\Python35\lib\site-packages\fdb\fbcore.py", line 3573, in execute
    self._ps = PreparedStatement(operation, self, True)
  File "C:\Users\Beto\AppData\Local\Programs\Python\Python35\lib\site-packages\fdb\fbcore.py", line 2182, in __init__
    "Error while preparing SQL statement:")
fdb.fbcore.DatabaseError: ('Error while preparing SQL statement:\n- SQLCODE: -104\n- Dynamic SQL Error\n- SQL error code = -104\n- Token unknown - line 10, column 1\n- CREATE', -104, 335544569)
César
  • 16,990
  • 6
  • 37
  • 76

2 Answers2

1

El método cursor.execute() sólo ejecuta una instrucción cada vez. Conectores como el de mysql permiten la ejecución múltiple, pero no he encontrado que éste de firebird lo permita.

Divide la query en sentencias individuales. En este momento estás ejecutando varias sentencias separadas por ;. Puedes dividirlo a mano e invocar cada una por separado, o puedes hacer algo parecido a ésto:

for q in sql2.split(";"):
    cx.execute(q)
con.commit()

Pero falla en la última sentencia, la que crea el TRIGGER, que tiene un ; interno. Tendrás que separarla a mano de las demás.

Todas las sentencias se ejecutan en la misma transacción que se consolida al salir de bucle con el con.commit(). Se puede hacer el commit después de cada ejecución, aunque he visto que fdb tiene instrucciones no estándares para hacerlo en un paso (autocommit) con execute_inmediate. (En el estándar DB-API, el autocommit se indica con un parámetro de la conexión a la base de datos).

ChemaCortes
  • 8,325
  • 18
  • 36
  • Como seria eso? perdon pero soy novato (un ejemplo) por favor @ChemaCortes –  May 11 '16 at 18:39
  • osea q me conviene mas execute_inmediate q execute? @ChemaCortes –  May 11 '16 at 18:58
  • No me deja usar execute_inmediate @ChemaCortes –  May 11 '16 at 19:41
  • Lo he escrito mal: `execute_immediate`. De todos modos, consulta la documentación del módulo. Y no, no quería sugerir que sea mejor usar este método ni que sea mejor el *autocommit* implícito. Mi recomendación es que no te salgas del estándar [DB-API2](https://www.python.org/dev/peps/pep-0249/), uses cursores (*transacciones*) y que hagas un `commit` explícito siempre. Y podrás usar cualquier base de datos con python. – ChemaCortes May 11 '16 at 23:22
  • No entendi bien pero en algo tienes razon firebird no es como las demas y ay q estarle buscando @ChemaCortes –  May 12 '16 at 00:45
  • como podría ejecutar varias consultas a la ves @ChemaCortes –  May 14 '16 at 22:26
  • No es recomendable ejecutar varias instrucción a la vez. Piensa en lo que puedes complicarte para procesar luego los valores devueltos. Insisto en que revises la documentación ([SQL Execution Basics](http://pythonhosted.org/fdb/usage-guide.html#sql-execution-basics)). – ChemaCortes May 15 '16 at 22:12
0

No se puede hacer todo en una sola sentencia, debes hacerlo asi:

con.execute_immediate('''
CREATE TABLE RUBY (
  Id BIGINT NOT NULL PRIMARY KEY,
  nombre VARCHAR(60) CHARACTER SET UTF8 NOT NULL,
  correo VARCHAR(60) CHARACTER SET UTF8 NOT NULL UNIQUE,
  pais VARCHAR(60) CHARACTER SET UTF8 NOT NULL,
  contra VARCHAR(60) CHARACTER SET UTF8 NOT NULL
  );''')
con.execute_immediate("CREATE GENERATOR gen_ruby_id;")
con.execute_immediate("SET GENERATOR gen_ruby_id TO 0;")
con.execute_immediate("""CREATE TRIGGER BI_RUBY_ID FOR RUBY
ACTIVE BEFORE INSERT
POSITION 0
AS
BEGIN
if (NEW.id is NULL) THEN NEW.id = GEN_ID(gen_ruby_id, 1);
END""")
con.commit()
LUK2009
  • 3
  • 1