I have a FDTable with TBooleanField.
The database is dBase IV.
I want to create the table with:
<TFDTable>.CreateTable(False, [tpTable]);
This works if I don't have a TBooleanField in the table.
In the SQL script that generated on CreateTable the TBooleanField is of type BOOLEAN. Is there something in property of FDConnection or FDTable that change the BOOLEAN to LOGICAL.
SQL Script:
CREATE TABLE ACT_01 (
ISDOC BOOLEAN,
DOCTYPE VARCHAR(1))
Must change in:
CREATE TABLE ACT_01 (
ISDOC LOGICAL,
DOCTYPE VARCHAR(1))
Ok, I can execute the sql myself without the createtable but I want to know if it is possible to change the BOOLEAN to LOGICAL from the methode TFDTable.CreateTable
FDConnection:
FDConnection1.Params.Add('DriverID=ODBC');
FDConnection1.Params.Add('ODBCDriver={Microsoft dBase Driver (*.dbf)}');
FDConnection1.Params.Add('Database=C:\Projects\Test Projects\DBase table\Data');
FireDAC uses hardcoded data types for generating CREATE command for all unsupported ODBC drivers (the ODBC command generator's GetColumnType method doesn't query driver for DBMS data type names).
What's more, FireDAC does not recognize any ftLogical data type, so you cannot create a custom data type mapping even though that's just what you were supposed to do here.
So, you're out of luck at this time.
Related
I am trying to create a new field in a FireDAC-compatible database with this PROCEDURE:
PROCEDURE CreateField(Connection : TFDConnection ; CONST TableName : STRING; F : TFieldDefinition);
VAR
Table : TFDTable;
BEGIN
Table:=TFDTable.Create(NIL);
TRY
Table.Connection:=Connection;
Table.TableName:=TableName;
Table.FieldDefs.Updated:=FALSE;
Table.FieldDefs.Update;
Table.FieldDefs.Add(F.FieldName,F.FieldType,F.MaxLen,NOT F.Nullable);
// Commit my changes to the database //
FINALLY
FreeAndNIL(Table)
END
END;
where
TYPE
TFieldDefinition = CLASS
PUBLIC
FieldName : STRING;
FieldType : TFieldType;
MaxLen : Integer;
Nullable : BOOLEAN;
END;
but I can't seem to "Commit" my changes back to the database (ie. end up executing an ALTER TABLE ADD [COLUMN] statement).
How do I commit my changes to the FieldDefs list of the table? Or is there some other way - using plain FireDAC - that I can use to create a new field in an existing table?
Note: There are already data in the table, so I can't simply "DROP" and then "CREATE" the table again.
FireDAC should understand the sytax used by the supported databases and use the appropriate syntax and decoration. See the documentation here: http://docwiki.embarcadero.com/RADStudio/Sydney/en/Preprocessing_Command_Text_(FireDAC)
TFieldDef is an internal descriptor of the fields in a TDataSet, it's not going to be used to update the table structure automatically. (Although you could write your own procedure that compares your TFieldDefs to the FireDAC MEta Data and creates the DDL (Data Definition Language) statements you need to execute in a TFDCommand ... )
To alter that table structure you will need to provide the DDL (SQL) statement that you execute with TFDCommand - the 'preprocessing' link above will explain how to write it in a dialect abstracted way.
If you use the appropriate FireDAC description it will automatically put in the appropriate SQL decoration for you so the syntax is valid. Depending on your SQL dialect and the FireDAC driver you may hit limitations. (For example using the ODBC driver FireDAC generally won't know the specific details of the underlying database - we had to implement a solution for SAP HANA which had exactly this challenge).
Bear in mind that some SQL dialects support features that others don't - so for example it's not safe to assume that you can position a column when you add it (which MySQL supports for example) as not all dialects allow that in an ALTER TABLE statement.
I'm using dephi 2010, which is getting difficult with me about installing the ADOX components. So I was wondering if there is a way to create a .mdb file without the use of the ADOXCatalog.
-Thank you.
Yes, this can be done without using an ADOXCatalog.
Place a TAdoConnection and e.g. a TAdoCommand on a form or datamodule. Set the TAdoCommand's Connection property to the TAdoConnection.
Then, in the AdoConnection's ConnectionString builder, select Microsoft OLE DB Driver for ODBC. Then, follow the ODBC wizard to set up a new MDB database. As you follow that through you will be able to create a File DSN (unless you are running Delphi as adminstrator), select the Access Jet driver, specify the database path (making sure it is somewhere writeable) and name, and then the wizard presents you with a button to click to create the MDB file.
Although it is not in English, there is a video here
https://www.youtube.com/watch?v=E_2hrER9oho
which shows you exactly how to do this. The ODBC connection string wizard should give you the option to create a new datasource and present you with a list like this to choose from:
Set the TAdoCommand's CommandText to something like
create table ATable (AName TEXT(40))
and call its Execute method at r/time to create a one-column table.
Btw, you could equally well use a TAdoQuery instead of the TAdoCommand component using its Sql property instead of the TAdoCommand's CommandTextproperty, and you should be able to use any valid DDL statements to define the tables in the database.
In MS SQL Server, you can declare local variables of any primitive type, or of a table type. This table is a normal table that you can run SELECT, INSERT, UPDATE and DELETE on, just like any other table, except that it's a local variable, not a part of the database itself.
I'm trying to do the same thing in Firebird, but it doesn't seem to like the syntax.
declare variable value int; --works fine
declare variable values table (value int); --Error: "Token unknown (table)"
Is there any way to do this? (And before anyone says "use a selectable stored procedure," that won't work. I need something I can dynamically run INSERT and SELECT on.)
Firebird doesn't support table variables the same way SQL Server does.
The close thing you have at your disposal is Global Temporary Tables (Requires Firebird 2.1 or greater)
(v.2.1) Global temporary tables (GTTs) are tables that are stored in the system catalogue with permanent metadata, but with temporary data. Data from different connections (or transactions, depending on the scope) are isolated from each other, but the metadata of the GTT are shared among all connections and transactions.
There are two kinds of GTT:
with data that persists for the lifetime of connection in which the specified GTT was referenced; and
with data that persists only for the lifetime of the referencing transaction.
You have to create the GTT beforehand.
CREATE GLOBAL TEMPORARY TABLE
...
[ON COMMIT <DELETE | PRESERVE> ROWS]
I have derived my own component from TAdoQuery in Delphi. I have overridden the DoAfterPost procedure; and in this code I create another query for the purpose of fetching the primary key associated with an inserted record (i.e. SELECT ##IDENTITY for SqlServer, SELECT LAST_INSERT_ID() for MySql, etc).
In the past I always used TAdoConnection for database connectivity. And in the "subquery" call made within DoAfterPost there was no problem because it was the SAME Session (these queries to retrieve last inserted primary keys assume a persistent database connection).
I recently made an option where instead of using a TAdoConnection connection, I am instead setting the ConnectionString property (for multi-thrading purposes). But this creates a problem because the spawned subquery does not use the same session as the main query. Hence it does not return the primary key value.
My question is, does TAdoQuery have any Connection property if the ConnectionString is used? I could then daisychain this connection/session to my subquery. Or is the only way to accomplish this via a TAdoConnection?
#M Schenkel, when you set the ConnectionString property of the TADOQuery component, the TAdoQuery create a new connection to the database with a new session id.
the ##IDENTITY SQL Server function return the last-inserted identity value in the current session , because that you need to use the same Connection (and session) for the insert statement and the query SELECT ##IDENTITY.
As workaround in sql server you can use the IDENT_CURRENT function wich is not limited to an session.
In MySql the LAST_INSERT_ID() function also works on a perconnection. therefore the behavior is similar to the function ##IDENTITY.
In short, the best option you have is to use an unique TAdoConnection object.
I am trying the devart ibdac components but I am having a little issue with the IBCTable component. On tables with autoinc (trigger based) when I try to post the data it says that the field with the autoincrement must have a value, whereas if I use a SQL query to insert it everything works fine.
Is there any workaround for this?
You need to set the following properties for the TIBCTable component to automatically fill out the fields with values from the same generator / sequence that you use in your trigger:
GeneratorMode
GeneratorStep
KeyFields
KeyGenerator
For more information see the documentation of the TIBCTable component, you will find all the properties with links to the base class they are introduced in.