So I'm transferring an old filemaker database to MySQL and some repeating fields are causing me some problems. I've read that the ODBC standard support those fields, only when their types is "Text" and that each repetition is concatenated with a certain delimiter (see page 47 (PDF)). However, I just can't reproduce this. All I get is the first repetition.
If I export the database to the .csv format, the fields are correctly concatenated, so I'm not completely stuck, but if possible, I'd like to be able to obtain the same result with the ODBC connection. Thanks!
With JDBC and Filemaker 12 I can access the repeating field using brackets as it was table beginning with index 1.
It should be the same in ODBC.
Of course I recommend to normalize but it can help to know there is other options.
In my experience the documentation about repeating fields is a lie. :)
If you can get it to work, please, please post an answer. But I imagine you'll have to do the workaround using the csv export.
My recommendation regarding this would be to normalize the repeating fields to a separate table within FileMaker and then perform the transfer of the data. You can create a related table in FileMaker and then use a script to populate the table with the repeating field values. Let me know if you need assistance writing such a script.
I want to provide details about #Signix answer above. I was able to fetch repeating fields from JDBC but it's tricky. At page 30 of FileMaker "ODBC and JDBC Guide", it states:
Note FileMaker repeating fields are supported like arrays.
Example
INSERT INTO mytable(repField[3]) VALUES (‘this is rep 3’)
SELECT repField[1], repField[2] FROM mytable
This is the only documentation! So in theory you could use this query:
ResultSet resultSet = fmStatement.executeQuery("SELECT id, repField[1], repField[2] FROM mytable");
But the tricky part is getting the results. The only way seems to use the column index.
System.out.println(resultSet.getString("repField[1]")); // fails, throws FMSQLException
System.out.println(resultSet.getString("repField[2]")); // fails, throws FMSQLException
System.out.println(resultSet.getString("repField")); // returns repField[1]
System.out.println(resultSet.getString(2)); // returns repField[1]
System.out.println(resultSet.getString(3)); // returns repField[2]
I think the reason is because fields are being named without their bracket parts.
System.out.println(resultSet.getMetaData().getColumnName(1)); // returns "id"
System.out.println(resultSet.getMetaData().getColumnName(2)); // returns "repField"
System.out.println(resultSet.getMetaData().getColumnName(3)); // returns "repField"
So when using resultSet.getString("repField") it returns the first column value with that name. It's stupid but it works.
Related
I'm working on a symfony application, and i need to insert multiple raws at once, Doctrine ORM is not a good option because for each raw it will open a connection to execute the query, to avoid this and have one connection inserting all the raws i used prepared statement of doctrine dbal and it works fine, except i need to get the ids of the inserted raws, it seems the only available function is lastinsertedid which returns only the last id not all the last inserted ones, how can i achieve this?
any help would be appreciated!
This is actually not related to doctrine at all. If you want all inserted id's it must be possible in MySQL. "It's unlikely that if doctrine don't have batch insert it will support returning list of ids after batch insert :)"
Check answers related to MYSQL:
How can I Insert many rows into a MySQL table and return the new IDs?
MySQL LAST_INSERT_ID() used with multiple records INSERT statement
But it's possible in postgresql (since you didn't mention you DB):
Retrieving serial id from batch inserted rows in postgresql
You can actually generate IDs before inserting content into database. For example, using random UUIDs.
This library might be of use: https://github.com/ramsey/uuid
use Ramsey\Uuid\Uuid;
$uuid4 = Uuid::uuid4();
echo $uuid4->toString()
I am working on a sort function for a table column that holds desk numbers and names.
This is a legacy program and was designed so that this column is nvarchar.
Because of this, the sort function cannot sort numerically as shown below:
Should I go into the database and alter this column to add leading zeros to number-only entries? Is this even do-able since the column is nvarchar?
Or should I add code at the object-level to add leading zeros just before the data is presented?
I would add one getter property in my class so it look like
public int Ordering
{
get
{
return int.Parse(CharColumn);
}
}
and when getting list of those objects simply order by that new property.
SQL Server is built upon SET Theory which states that, if you order your result set, you get non-relational data.
I would create another database column with the numeric value (there may be some columns that don't convert well, make sure you identify these and work to convert them). Then I would work to convert your application to use the new values. If the conversion is too great you could make sure all new development uses the new column and old code is migrated the next time someone touches it.
The risk to your approach is too fold, storing them in varchar is inefficient with both memory and processing power. Adding zeroes will help with the sorting but not fix the root issue.
Here is another question that I think will help you: SQL Server : error converting data type varchar to numeric
I need to be able to run a query such as
SELECT * FROM atable WHERE MyFunc(afield) = "some text"
I've written MyFunc in a VB module but the query results in "Undefined function 'MyFunc' in expression." when executed from .NET
From what I've read so far, functions in Access VB modules aren't available in .NET due to security concerns. There isn't much information on the subject but this avenue seems like a daed end.
The other possibility is through the CREATE PROCEDURE statement which also has precious little documentation: http://msdn.microsoft.com/en-us/library/bb177892%28v=office.12%29.aspx
The following code does work and creates a query in Access:
CREATE PROCEDURE test AS SELECT * FROM atable
However I need more than just a simple select statement - I need several lines of VB code.
While experimenting with the CREATE PROCEDURE statement, I executed the following code:
CREATE PROCEDURE test AS
Which produced the error "Invalid SQL statement; expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'."
This seems to indicate that there's a SQL 'PROCEDURE' statement, so then I tried
CREATE PROCEDURE TEST AS PROCEDURE
Which resulted in "Syntax error in PROCEDURE clause."
I can't find any information on the SQL 'PROCEDURE' statement - maybe I'm just reading the error message incorrectly and there's no such beast. I've spent some time experimenting with the statement but I can't get any further.
In response to the suggestions to add a field to store the value, I'll expand on my requirements:
I have two scenarios where I need this functionality.
In the first scenario, I needed to enable the user to search on the soundex of a field and since there's no soundex SQL function in Access I added a field to store the soundex value for every field in every table where the user wants to be able to search for a record that "soundes like" an entered value. I update the soundex value whenever the parent field value changes. It's a fair bit of overhead but I considered it necessary in this instance.
For the second scenario, I want to normalize the spacing of a space-concatenation of field values and optionally strip out user-defined characters. I can come very close to acheiving the desired value with a combination of TRIM and REPLACE functions. The value would only differ if three or more spaces appeared between words in the value of one of the fields (an unlikely scenario). It's hard to justify the overhead of an extra field on every field in every table where this functionality is needed. Unless I get specific feedback from users about the issue of extra spaces, I'll stick with the TRIM & REPLACE value.
My application is database agnostic (or just not very religious... I support 7). I wrote a UDF for each of the other 6 databases that does the space normalization and character stripping much more efficiently than the built-in database functions. It really annoys me that I can write the UDF in Access as a VB macro and use that macro within Access but I can't use it from .NET.
I do need to be able to index on the value, so pulling the entire column(s) into .NET and then performing my calculation won't work.
I think you are running into the ceiling of what Access can do (and trying to go beyond). Access really doesn't have the power to do really complex TSQL statements like you are attempting. However, there are a couple ways to accomplish what you are looking for.
First, if the results of MyFunc don't change often, you could create a function in a module that loops through each record in atable and runs your MyFunc against it. You could either store that data in the table itself (in a new column) or you could build an in-memory dataset that you use for whatever purposes you want.
The second way of doing this is to do the manipulation in .NET since it seems you have the ability to do so. Do the SELECT statement and pull out the data you want from Access (without trying to run MyFunc against it). Then run whatever logic you want against the data and either use it from there or put it back into the Access database.
Why don't you want to create an additional field in your atable, which is atable.afieldX = MyFunc(atable.afield)? All what you need - to run UPDATE command once.
You should try to write a SQL Server function MyFunc. This way you will be able to run the same query in SQLserver and in Access.
A few usefull links for you so you can get started:
MSDN article about user defined functions: http://msdn.microsoft.com/en-us/magazine/cc164062.aspx
SQLServer user defined functions: http://www.sqlteam.com/article/intro-to-user-defined-functions-updated
SQLServer string functions: http://msdn.microsoft.com/en-us/library/ms181984.aspx
What version of JET (now called Ace) are you using?
I mean, it should come as no surprise that if you going to use some Access VBA code, then you need the VBA library and a copy of MS Access loaded and running.
However, in Access 2010, we now have table triggers and store procedures. These store procedures do NOT require VBA and in fact run at the engine level. I have a table trigger and soundex routine here that shows how this works:
http://www.kallal.ca/searchw/WebSoundex.htm
The above means if Access, or VB.net, or even FoxPro via odbc modifies a row, the table trigger code will fire and run and save the soundex value in a column for you. And this feature also works if you use the new web publishing feature in access 2010. So, while the above article is written from the point of view of using Access Web services (available in office 365 and SharePoint), the above soundex table trigger will also work in a stand a alone Access and JET (ACE) only application.
Is there a way to further restrict the lookup performed by a database lookup functoid to include another column?
I have a table containing four columns.
Id (identity not important for this)
MapId int
Ident1 varchar
Ident2 varchar
I'm trying to get Ident2 for a match on Ident1 but wish it to only lookup where MapId = 1.
The functoid only allows the four inputs any ideas?
UPDATE
It appears there is a technique if you are interested in searching across columns that are string data types. For those interested I found this out here...
Google Books: BizTalk 2006 Recipes
Seeing as I wish to restrict on a numberic column this doesn't work for me. If anyone has any ideas I'd appreciate it. Otherwwise I may need to think about my MapId column becoming a string.
I changed the MapId to MapCode of type char(3) and used the technique described in the book I linked to in the update to the original question.
The only issue I faced was that my column collations where not in line so I was getting an error from the SQL when they where concatenated in the statement generated by the map.
exec sp_executesql N'SELECT * FROM IdentMap WHERE MapCode+Ident1= #P1',N'#P1 nvarchar(17)',N'<MapCode><Ident2>'
Sniffed this using the SQL Profiler
I currently have multiple queries that query data from a few tables linked through ODBC, and some temporary tables that are edited through the user interface. I have complex criteria in my queries such as:
SELECT * from ThingsData
WHERE (Thing In(SELECT Thing from ListOfThings) AND getThingFlag() = True);
In this case Thing is a field and ListOfThings is a temporary table that the user defines from the user interface. Basically, the user puts together a list of the field Thing that he/she wants to filter the data based on and I want to query only the data that matches the Thing values that the user adds to his/her list. Currently, the data I am querying is in the linked ODBC table, and the temp table ListOfThings is just a regular, local table and everything works peachy. I want to get rid of the linked table and use a pass through query instead. However, when i do that, unless the criteria is incredibly simplistic, i get an error:
"ODBC--Call Failed. Invalid object name ListOfThings."
If I dont have any criteria it works fine.
Long story short: In a pass through query, how do I apply criterias that include SELECTs and functions from my modules and just basically filter the pass through table based on data from my local tables?
What is at the other end of that ODBC link? In a pass-through query you will have to honor the syntax required by the database server, not Access syntax. I would first suspect that you can't have mixed case table names and I would try listofthings as the name.
If you have a tool that can be used to test queries directly against the database server, get the query working there and then simply cut and paste it into an Access pass-through query.