PDA

Ver la Versión Completa : ¿Como creo una tabla desde un fichero .ini?


Thoma
28-07-2011, 15:28:02
Teniendo resuelto el problema de como crear una BD si esta no existe, ahora vuelvo a apelar a vuestra sabiduría.
Mi idea es crear las tablas necesarias desde un fichero .INI
(He oído hablar de archivos .cmp donde pones las sentencias SQL, pero no sé como se usan).
¿Que componente puedo utilizar para cuando lea una sección del fichero .INI ejecute la sentencia SQL?

[TUSUARIOS]
CREATE TABLE TUSUARIOS
(
"IDUSUARIO" INTEGER NOT NULL,
"USUARIO" VARCHAR(50) ,
"CLAVEACCESO" VARCHAR(50) ,
"FECHACADUCIDAD" TIMESTAMP ;
CONSTRAINT "TUSUARIOSPRIMARYKEY" PRIMARY KEY ("IDUSUARIO")
);
CREATE UNIQUE INDEX "USUARIOKEY" ON "TUSUARIOS"("USUARIO");

maeyanes
28-07-2011, 15:53:52
Hola...

Falta información, que base de datos y que componentes estás usando para conectarte a esa base de datos...



Saludos...

Thoma
28-07-2011, 16:42:10
Utilizo Firebird, y para la creación de la BD estoy utilizando el TIBDataBase

maeyanes
28-07-2011, 16:55:26
Hola...

Si usas Firebird y los componentes IBX, estos tienen un componente llamado TIBScript que te puede servir para lo que necesitas.

Ahora, los archivos INI usan un formato específico para guardar los valores y no funcionan de la forma como quieres hacerlo. Yo te recomendaría que crees archivos de script (.sql) con la definición de la tabla y en el ini hagas referencia a este archivo.

Archivo INI:

[Tablas]
TUsuarios=DefTablas\usuarios.sql


usuarios.sql:

create table TUsuarios(
IdUsuario integer not null,
usuario varchar(50),
/* etc */
);
create unique index UsuarioKey on TUsuarios(usuario);


Desde tu aplicación lees el archivo INI, obtienes la ruta del archivo SQL, lo cargas en el componente TIBScript y ejecutas el script.



Saludos...

Thoma
28-07-2011, 17:26:16
maeyanes, ante todo darte las gracias por tu ayuda.
A ver si capto un poco como funciona.
Tengo un TIBDataBase: Name: dbCrearBD
E añadido un TIBScript: Name ScriptBD
DataBase: dbCrearBD
En c:\BD\tbsistema.ini
[Tablas]
TUsuarios=c:\BD\usuarios.sql

En c:\BD\usuarios.sql
CREATE TABLE TUSUARIOS
(
"IDUSUARIO" INTEGER NOT NULL,
"USUARIO" VARCHAR(50) ,
"CLAVEACCESO" VARCHAR(50) ,
"FECHACADUCIDAD" TIMESTAMP ;
CONSTRAINT "TUSUARIOSPRIMARYKEY" PRIMARY KEY ("IDUSUARIO")
);
CREATE UNIQUE INDEX "USUARIOKEY" ON "TUSUARIOS"("USUARIO");


function LeerCampoIni(etiqueta,texto,campo:string):string;
begin
Result:='';
with TIniFile.Create(sFileIni) do
try
Result:=ReadString(etiqueta,texto,'');
Free;
finally
Free;
end;
end;
--------------------------------------------------------------------------
sSQL:=LeerCampoIni('Tablas','TUsuarios','');
if sSQL<>'' then begin
if dbCrearBd.Connected then dbCrearBd.Connected:=False;
dbCrearBd.DatabaseName:=NameBD;
dbCrearBd.Connected:=True;
with ScriptBD do try
ScriptBD.Script :=sSQL;
except

end;
end;



Me da el siguiente error
[DCC Error] E2010 Incompatible types: 'TStrings' and 'string'

maeyanes
28-07-2011, 17:36:19
Hola...

Tú código está bien, solo que estás obteniendo mal la información. Una version corregida sería:


// La función obtiene la ruta del archivo SQL desde el archivo INI
function GetFilePath(const Section, Key, Value: string): string;
begin
with TIniFile.Create(sFileIni) do
try
Result := ReadString(Section, Key, Value)
finally
Free
end
end;

// Usamos la función:
ScriptFilePath := GetFilePath('Tablas', 'TUsuarios', 'C:\DB\usuarios.sql');
// Configuras componentes
ScriptDB.Script.LoadFromFile(ScriptFilePath); // Cargas el script desde el archivo directamente en la propiedad.
ScriptDB.ExecuteScript;



Saludos...

Thoma
28-07-2011, 18:03:51
de nuevo Gracias, ya no me da el error al compilar, pero parecer ser que me crea la BD (abriéndome una ventana para el usuario[SYSDBA] y password[masterkey])
sin la tabla.
Voy a hacer unas comprobaciones....

Thoma
28-07-2011, 18:39:32
Cuando me crea la BD según el código que os muestro a continuación, se me abre una ventana pidiéndome el usuario y la password
¿como es posible si lo tengo definido al crea la BD?




//------------------------------------------------------------------------------
//********************************************[ CReamos La Base De Datos ]******
//------------------------------------------------------------------------------
function crearBD (unidadBD, rutaBD, nameBD, extBD:string; empresaBD:Integer):Boolean;
var
sEmp:string;
begin
result := false;
if empresaBD < 10 then begin
sEmp:='0'+ IntToStr(empresaBD);
end else begin
sEmp:=IntToStr(empresaBD);
end;
if empresaBD=0 then sCad:= unidadBD+rutaBD+nameBD+extBD
else sCad:= unidadBD+rutaBD+nameBD+sEmp+extBD;
try
//--------------------------------------------------------------------------
//*********** [ creamos la base de datos ]
//--------------------------------------------------------------------------
DMSistema.dbCrearBd.DatabaseName := sCad;
DMSistema.dbCrearBd.Params.Clear;
DMSistema.dbCrearBd.Params.Add('user ''SYSDBA''');
DMSistema.dbCrearBd.Params.Add('password ''masterkey''');
DMSistema.dbCrearBd.Params.Add('PAGE_SIZE = 4096');
DMSistema.dbCrearBd.SQLDialect := 3;
DMSistema.dbCrearBd.CreateDatabase;
//--------------------------------------------------------------------------
//*********** [ creamos la Tabla de usuarios ]
//--------------------------------------------------------------------------
sCad:= unidadBD+ruta+'usuarios.sql';
sSQL:=LeerCampoIni('Tablas','TUsuarios',sCad);
if sSQL<>'' then begin
if DMSistema.dbCrearBd.Connected then DMSistema.dbCrearBd.Connected:=False;
DMSistema.dbCrearBd.DatabaseName:=NameBD;
DMSistema.dbCrearBd.Connected:=True;
with DMSistema.ScriptBD do try
DMSistema.ScriptBD.Script.LoadFromFile(sSQL);
DMSistema.ScriptBD.ExecuteScript;
except
end;
end;

result := True;
except
result := false;
end;
end;

José Luis Garcí
28-07-2011, 18:49:47
Hola Thoma, primero que nada me parece un buen trabajo el que estas desarrollando, yo lo que hago todo lo vuelco a un memo y luego creo la base de datos. En cuanto a tú pregunta en el IBDatabase sería

IBDatabase1.LoginPrompt:=False;

Espero te ayude.

Thoma
28-07-2011, 21:35:30
Hola Jose Luis, gracias por tu comentario, la verdad es me está costando un poco el Delphi, pero veo que es bastante potente y en ello estoy. Voy a probar lo que me dices del “LoginPrompt” y te comento.
¿Me podrías explicar un poco lo del memo que me comentas?
Un saludo..

José Luis Garcí
29-07-2011, 08:25:05
Te comento Thoma. lo que tu haces es volcarlo directamente al IbSript, en su SQL, en mi sistemacreo un init por taba con varias caracteristicas y entre lo que vuelco al init tengo en proyecto volcar la sentencia, para ello lo pasoa un memo en vez de el ibscript, con lo que puedo guardarlo independientemente, ver la sentencia antes de ejecutarla, etc, cargala es muy simple sólo tendrias que volcar el contenido del memo en el ibScript.

Lepe
29-07-2011, 08:48:42
En lugar de un Memo, sugiero un componente SynEdit, gratuito y open source, en apenas 10 segundos ya reconoce el SQL (colores en palabras reservadas y demás), se recomienda su uso.

Thoma
29-07-2011, 15:10:58
¿Puedo utilizar el Script para insertar un registro en la tabla?
he utilizado el:

Script.LoadFromFile(sSQL);


para crear la tabla en la base de datos, y quisiera insertar el primer registro pero sin utilizar un archivo externo (.sql) sino desde el mismo delphi


Script.Clear;
sSQL:='';
sSQL:='INSERT INTO TUsuarios (IDUSUARIO,USUARIO,CLAVEACCESO) values (1,' + QuotedStr('') + ',' + QuotedStr('0000');
Script.¿?
ExecuteScript;



de este modo si me funciona

//------------------------------------------------------------------
//*********** [ Creamos el primer registro en la tabla ]
//------------------------------------------------------------------
sCad:= unidadBD+ruta+'regusuarios.sql';
sSQL:=LeerCampoIni('RegUsuario','RegUsuarios',sCad);
if sSQL<>'' then begin
with DMSistema.ScriptBD do try
Script.Clear;
Script.LoadFromFile(sSQL);
ExecuteScript;
except
end;
end;

maeyanes
29-07-2011, 15:13:47
Hola...


Script.SQL.Text := sSQL; // Sustituyes todo el script
// o
Script.SQL.Add(sSQL); // Agregar la línea al script existente


Solo tienes que checar que cada línea termine con ;...


Saludos...

Thoma
29-07-2011, 15:40:19
Hola maeyanes.
no me salen las propiedades .SQL.Text del Script

[DCC Error] URutinas.pas(193): E2003 Undeclared identifier: 'SQL'
[DCC Error] URutinas.pas(193): E2066 Missing operator or semicolon
[DCC Fatal Error] Gestion.dpr(13): F2063 Could not compile used unit 'FrIndex.pas'

maeyanes
29-07-2011, 15:44:29
Hola...

Disculpa, me confundí con el nombre de la propiedad:


with DMSistema.ScriptBD do
try
// Si vas a usar Script.Add
Script.Clear;
Script.Add(sSQL);
// Si vas a usar Script.Text
Script.Text := sSQL;
ExecuteScript;
except
end;



Saludos...

Thoma
29-07-2011, 16:37:26
ahora me compila bien, pero con este código no me inserta el registro en la tabla


Script.Clear;
Script.Text := 'INSERT INTO TUsuarios (IDUSUARIO,USUARIO,CLAVEACCESO) values (1,' + QuotedStr('admin')+ QuotedStr('0000')+')';
ExecuteScript;


sin embargo desde el editor SQL del IBExpert si me inserta el registro

INSERT INTO TUsuarios (IDUSUARIO,USUARIO,CLAVEACCESO) values (1,'admin','0000')

maeyanes
29-07-2011, 16:41:29
Hola...

La sentencia INSERT está mal generada, le falta el paréntesis final, de seguro te envía una excepción, la cual estás escondiendo en tu código. La forma correcta sería:


sSQL := 'insert into TUsuarios values(1, ''admin'', ''0000'');'



Saludos...

Thoma
29-07-2011, 16:48:27
OK, lo encontre. me faltaba separar con la ',' entre (admin) y (0000)
voy a probar como tu me dices.

Thoma
29-07-2011, 16:52:33
con este script si me funciona.

Script.Text := 'INSERT INTO TUsuarios (IDUSUARIO,USUARIO,CLAVEACCESO) values (1,' + QuotedStr('admin')+','+QuotedStr('0000')+')';

me faltaba poner el último +')';