Infor LN and Baan 4GL Embedded SQL Select Generator
This generator writes Baan IV and Infor LN embedded SQL for 3GL and 4GL scripts: table declarations, a select with host variables, index ordering and a full selectdo, selectempty, selecterror, endselect loop. It also gives a join variant and a call example, so you can paste it into a UI script, DLL or DAL in Program Scripts / Libraries (ttadv2530m000).
Fill in
Logical table code without the leading t, e.g. tdsls401 (sales order lines).
Use :variable for host variables declared in the script.
Declaration
|****************************************************************************** |* Embedded SQL on tdsls401 |****************************************************************************** declaration: table ttdsls401 | main table table ttcibd001 | only needed for the join variant
Select loop in a function
functions:
function long read.tdsls401.rows(domain tcorno i.orno)
{
long row.count
row.count = 0
select tdsls401.orno, tdsls401.pono, tdsls401.item, tdsls401.qoor
from tdsls401
| read only, no lock
where tdsls401.orno = :i.orno
order by tdsls401._index1
| all matching rows
selectdo
row.count = row.count + 1
| the selected columns of tdsls401 hold the current row here
| with for update: change fields, then db.update(ttdsls401, db.retry)
selectempty
| no row matched the where clause
row.count = 0
selecterror
| the query failed, log or report it
row.count = -1
endselect
return(row.count)
}Variant with a join
function long read.tdsls401.with.tcibd001(domain tcorno i.orno)
{
long row.count
row.count = 0
select tdsls401.orno, tdsls401.pono, tdsls401.item, tdsls401.qoor, tcibd001.dsca
from tdsls401, tcibd001
where tdsls401.orno = :i.orno
and tcibd001.item = tdsls401.item
order by tdsls401._index1
selectdo
row.count = row.count + 1
| tcibd001.dsca is filled for the current tdsls401 row
selectempty
row.count = 0
endselect
return(row.count)
}Calling it
| for example in a choice or field section of the session script long lines.found lines.found = read.tdsls401.rows(tdsls401.orno) if lines.found <= 0 then | nothing to process endif
Check the generated statement against the SQL programming chapter of the Infor ES Programmer's Guide for your Tools version. The lock and row limit options insert either the clause or a comment line, so the statement stays valid either way. With for update, commit with commit.transaction() in a UI or 3GL script, but never commit inside a DAL hook. The example function argument and the call assume an order number domain; change both if you change the where clause.
Get your LN queries reviewed
Send us a slow or failing embedded SQL statement and your LN and Tools versions, and we will suggest an index-friendly rewrite.
Optional. The tool and every export work without this. No spam.
How to use it
Enter the logical table code (tdsls401, not ttdsls401100), the columns you need, and a where clause that uses host variables with a leading colon, such as :i.orno. Pick whether rows are locked for update and whether only the first row is read. The output declares the table with the t prefix, wraps the select in a function that returns the row count, and adds a join variant against a second table such as item general data (tcibd001). Delete the variant you do not need. Select only the columns you use: a narrow column list is cheaper, and columns you did not select are not filled in the record buffer inside selectdo.
- Declare every table in the select with table t<code> in the declaration section
- Host variables are script variables or function arguments prefixed with a colon
- order by <table>._index1 orders by the table's first index
Embedded SQL versus database SQL
Embedded SQL uses logical LN names. The database driver translates them into physical names: on SQL Server or Oracle, tdsls401 in company 100 is the table ttdsls401100 and the column orno is t_orno. That is why an ad hoc query in SQL Server Management Studio looks different from the 4GL code, and why you should not copy t_ names into a script. Embedded SQL runs in the current company of the session; a query across companies has to say so explicitly, and you should test that against your own version before relying on it. References between tables (for example item on the order line pointing to tcibd001) are always expressed with logical table and field names.
Worked example
With the defaults the generator reads all lines of one sales order: select tdsls401.orno, tdsls401.pono, tdsls401.item, tdsls401.qoor from tdsls401 where tdsls401.orno = :i.orno order by tdsls401._index1. Inside selectdo, tdsls401.qoor holds the ordered quantity of the current line, so you can total it or test it. If the order has no lines, selectempty runs once and the function returns 0; if the query fails, selecterror runs and the function returns -1. Switch the row limit to as set with 1 rows when you only need to know whether a line exists, which avoids reading the whole set.
Common mistakes
Forgetting the table declaration gives a compile error on the select. Using for update without a following db.update and commit leaves rows locked until the transaction ends. Calling other database actions on the same table inside a long selectdo loop can disturb the set you are reading; collect keys first if you must update many rows. Writing a where clause on non-indexed fields over a large table such as tdsls401 forces a full scan, so filter on the leading fields of an index when you can. Finally, never commit inside a DAL hook: the DAL runs inside the caller's transaction.
Frequently Asked Questions
What is the difference between selectdo and selectempty in Baan 4GL?
selectdo is the body that runs once for every row the select returns. selectempty runs once when no row matches. selecterror runs when the query itself fails. The loop closes with endselect. Put row processing in selectdo and the not-found handling in selectempty instead of testing a counter afterwards.
What does as set with 1 rows do?
It limits the result set to one row, so the database stops after the first match. Combined with order by on an index it gives you the first or, with descending order, the last record by that index. Use it for existence checks and lookups instead of reading a full set and breaking out of the loop.
Why do column names start with t_ in SQL Server but not in my script?
LN stores each logical table as a physical table named t, the table code and the company number, for example ttdsls401100, and prefixes every column with t_. Embedded SQL in scripts uses the logical names and the driver translates them. Only direct database queries outside LN use the physical names.
Is this useful for Infor LN technical training?
Yes, as a starting point. New LN technical consultants usually learn the select loop first because it appears in nearly every UI script, DLL and DAL. Generate a few variants, compile them in a test VRC and step through them with the debugger to see when each section runs.
If your team wants to ask LN about sales orders and items in plain English, with the same logical tables and roles, we can run that on your own servers.
Related Tools
Infor LN DAL Script Template Generator
Generate a Data Access Layer (DAL) script skeleton for an LN table with object hooks, a field check hook, a mandatory hook and error message handling.
Developer ToolsInfor LN Report Script Template Generator
Generate a 4GL report script for an LN report with program sections, layout sections, a suppress condition and a running total.
Infor LN & BaanInfor LN SQL Query Generator
Fill in the table, company number and key range to get read-only SQL for the LN database, with the physical table name built for you.
Infor LN & BaanInfor LN 4GL Session Script Template
Generate a clean Baan / Infor LN 4GL session script skeleton with declaration, field, choice and table I/O sections.
More Developer Tools tools
See all- Infor LN 4GL Database Insert/Update Transaction Generator
- Infor LN AFS (stpapi) Session Automation Script Generator
- SAP Sales Order ABAP SELECT Generator (VBAK, VBAP, VBFA)
- SAP Sales Order Create BAPI ABAP Generator (BAPI_SALESORDER_CREATEFROMDAT2)
- SAP ABAP Open Items SELECT Generator
- SAP ACDOCA SQL Query Generator
- SAP QM Inspection Lot ABAP SELECT Generator
- SAP Quality Notification Pareto SQL Query Generator
- SAP QM Usage Decision BAPI Skeleton
Keep exploring
Free tools
- Infor LN 4GL Database Insert/Update Transaction GeneratorFill in table, key and fields to get a Baan/LN function that locks the record, writes it with db.retry, commits, and aborts cleanly on error.
- Infor LN 4GL Session Script TemplateGenerate a clean Baan / Infor LN 4GL session script skeleton with declaration, field, choice and table I/O sections.
- Infor LN SQL Query GeneratorFill in the table, company number and key range to get read-only SQL for the LN database, with the physical table name built for you.
ERP fixes and how-tos
- Baan IV to Infor LN migration checklistPlan a Baan IV to Infor LN move as a re-implementation, not a patch: inventory customizations, convert data, rebuild logic, and run a real parallel test.
- Infor LN Process Variables: Meaning, Setting and InspectingWhat process variables and bshell environment variables mean in Infor LN, how developers read and set them, and where to look when behaviour differs per user.
- Private AI Layer for Baan On-Prem: Reference ArchitectureReference architecture to add a private AI assistant to Baan on-prem: data access paths, retrieval, permissions, sizing and rollout, no cloud needed.
Guides
- BAAN 5 to Infor LN Complete Migration GuideMigrate from BAAN 5 to Infor LN comprehensively. 4GL analysis, data transformation, business process mapping, and organizational change management.
- Baan 4GL Modernization: Strategies for Legacy CodeBaan 4GL modernization strategies: inventory legacy sessions, retire dead code, convert customizations to LN extensions, and de-risk your Baan installed base.
- Baan ERP End of Life: What Are Your Real Options?Baan IV and Baan V are end-of-life. Explore your migration options to Infor LN, CloudSuite, or alternative ERPs with realistic timelines and costs.
Integrations
- How to add AI agents to Baan IV and Baan VHow to add AI agents to Baan IV or Baan V: tool layer over read-only database access and AFS, human approval on writes, and an on-prem model. A practical guide.
- How to use ChatGPT with Baan IV and Baan VUsing ChatGPT with Baan IV or Baan V: exports versus live access, custom GPT actions, enterprise data controls, and when a private on-prem model is the safer choice.