1. Foreign key referencing
The foreign key is a common concept for various relational databases. In a relational table, you can define one or multiple fields as the foreign key. The foreign key field values can be associated with the data in another table. For example, in the game scoring report, player scores are usually recorded with the player ID. To get the details of this player from another player profile table using the player ID, you can query in the player profile table according to the player ID. In this case, the player ID field can be set as the foreign key.
The foreign key can associate two relational tables and help ensure the data consistency, so as to facilitate some cascade operations. Take the above game scoring report as an example. If defining the player ID as the foreign key field, then the player name, country, age, and other data can be queried at the same time while getting the game scoring record of the player.
In this example of foreign key definition, it is actually equal to referencing the records in the player data table from the game scoring record table. The core idea of foreign key concept is to reference another record.
In esProc, unlike the database, there is no particular requirement on the data type of record fields. In other words, esProc users can get the value at will. Thanks to this convenience, in the esProc TSeq, fields can be directly assigned with records for referencing. The foreign key associating can thus be established naturally and straightforwardly.
For example, create an employee education background table comprising the employee ID field and education field. This example is designed to illustrate the way the esProc foreign key references, and the education field is simply set through the looping in proper order:
A | B | C | |
1 | =create(ID,Education) | [BS,BA,MS,MA,MBA,MEE,MPA,PhD] | =B1.len() |
2 | for 500 | =B1((A2-1)%C1+1) | |
3 | >A1.insert(0,A2,B2) |
At this point, associate this TSeq with employee table EMPLOYEE. A foreign key field Info can be added to the education table so as to reference the records in the table EMPLOYEE with the foreign key field values:
A | B | C | |
1 | =create(ID,Education) | [BS,BA,MS,MA,MBA,MEE,MPA,PhD] | =B1.len() |
2 | for 500 | =B1((A2-1)%C1+1) | |
3 | >A1.insert(0,A2,B2) | ||
4 | $ select * from EMPLOYEE | =A1.derive(A4.select@1(EID==ID):Info) |
To this point, the TSeq in B4 is as follows. In this TSeq, the Info field is the employee record on which you can double-click to query.
With the record reference, the foreign-key-related query becomes more convenient to implement. The query statement gets much more clear and intuitive. The record fields can be used in the same way of using the normal fields or records. For example, list the data of serial number, full name, education background, state, and department:
A | B | C | |
1 | =create(ID,Education) | [BS,BA,MS,MA,MBA,MEE,MPA,PhD] | =B1.len() |
2 | for 500 | =B1((A2-1)%C1+1) | |
3 | >A1.insert(0,A2,B2) | ||
4 | $ select * from EMPLOYEE | =A1.derive(A4.select@1(EID==ID):Info) | |
5 | =B4.select(Info.STATE== “Ohio”) | =A5.new(ID,Info.NAME+” “+Info.SURNAME:FullName,Education,Info.STATE:State,Info.DEPT:Dept) |
The following is B5’s result:
In esProc, not only the record of other TSeq but also that of the current TSeq can be assigned to the foreign key field.
In esProc, besides the function A.derive() for assigning a certain field of records with the objects of entire records when adding fields to the newly-generated TSeq; the function A.run() can be used to assign value to the existing fields. For example:
A | B | C | |
1 | =create(ID,Education) | [BS,BA,MS,MA,MBA,MEE,MPA,PhD] | =B1.len() |
2 | for 500 | =B1((A2-1)%C1+1) | |
3 | >A1.insert(0,A2,B2) | ||
4 | $ select * from EMPLOYEE | >A1.run(ID=A4.select@1(EID==A1.ID)) |
In B4, modify the employee serial number field in the Education Background TSeq to the corresponding records. In A1, the TSeq is as follows:
If the primary key of the corresponding table is a single field, you can also use the function A.switch():
A | B | C | |
1 | =create(ID,Education) | [BS,BA,MS,MA,MBA,MEE,MPA,PhD] | =B1.len() |
2 | for 500 | =B1((A2-1)%C1+1) | |
3 | >A1.insert(0,A2,B2) | ||
4 | $ select * from EMPLOYEE | >A1.switch(ID,A4) |
The TSeq in A1 is the same to that in the previous example, but much more concise and clear. One thing to note is that the switch function can be used to have the primary key and specified fields in theTSeq associated automatically. If the primary key of TSeq is not the first field, you need to set it with the function T.primary(). For example, the STATE field of employee table is associated with the STATE data table:
A | B | C | |
1 | =create(ID,Education) | [BS,BA,MS,MA,MBA,MEE,MPA,PhD] | =B1.len() |
2 | for 500 | =B1((A2-1)%C1+1) | |
3 | >A1.insert(0,A2,B2) | ||
4 | $ select * from EMPLOYEE | >A1.switch(ID,A4) | |
5 | $ select * from STATES | >A4.switch(STATE,A5.primary(NAME)) |
In this case, the State information can be further viewed in the employee data of TSeq in A1:
To this point, the query or computation based on multi-table association can be further processed. For example, find the state, in which the employees are located, has a population of below 1,000,000:
A | B | C | |
1 | =create(ID,Education) | [BS,BA,MS,MA,MBA,MEE,MPA,PhD] | =B1.len() |
2 | for 500 | =B1((A2-1)%C1+1) | |
3 | >A1.insert(0,A2,B2) | ||
4 | $ select * from EMPLOYEE | >A1.switch(ID,A4) | |
5 | $ select * from STATES | >A4.switch(STATE,A5.primary(NAME)) | |
6 | =A1.select(ID.STATE.POPULATION< 1000000) |
As can be seen, the record-referencing foreign key can make the query syntax of multi-table association more concise and readable with an improved computing speed.
2. Referencing sets
In assignment, esProc fields can be assigned with records or sets in a similar way – referencing the set in the foreign key field. In most cases, what is referenced in the foreign key fields is the RSeq composed of records from other TSeqs. Please notice that the “Foreign Key Field” is not the same thing as the foreign key field in the database. It is much more like the query to reference the sub table data from the primary table with SQL.
Like the foreign key referencing, fields can be added when generating the TSeq. With the function derive, the foreign key field can be assigned with RSeqs, for example:
A | |
1 | $ select NAME,ABBR from STATES |
2 | $ select * from EMPLOYEE |
3 | =A1.derive(A2.select(STATE==A1.NAME):Employees) |
In A3, add foreign key field Employees to A1, and assign this field with the employees in corresponding states, then return a new TSeq. By doing so, all values of Employees fields in the TSeq are RSeq, as shown below:
For the foreign key field referencing sets, they can be called directly as the fields of TSeq. The values of foreign key field can be taken as the set for direct use in the computation. For example, add the field Count and compute the total employees in each state:
A | |
1 | $ select NAME,ABBR from STATES |
2 | $ select * from EMPLOYEE |
3 | =A1.derive(A2.select(STATE==A1.NAME):Employees) |
4 | =A3.derive(Employees.count():Count) |
The total number of employees can be computed with the foreign key, and the resulting TSeq is shown in A4:
Like records being referenced, the sets or RSeqs are referenced in the foreign key field. The expressions on foreign key field can also be used to solve the multi-table-association query, filtering, and other problems. For example, find the states in which there are more than 50 employees:
A | |
1 | $ select NAME,ABBR from STATES |
2 | $ select * from EMPLOYEE |
3 | =A1.derive(A2.select(STATE==A1.NAME):Employees) |
4 | =A3.derive(Employees.count():Count) |
5 | =A4.select(Employees.len()>50) |
By referencing sets in foreign key field, the syntax of multi-table-association query can be more clear and intuitive. In the TSeq of A4, the sole purpose of introducing the field Count is to have a more clear view of the result. This field is not used when filtering records in A5.
When referencing sets in a TSeq field, the switch function cannot be used, but the function A.run() can be used to assign values to the existing fields. For example:
A | |
1 | =12.new(#:ID,string(date(“2000-“+string(#)+”-1″),”MMMM”):Month,Employees) |
2 | $ select EID,NAME+’ ‘+SURNAME FULLNAME, BIRTHDAY from EMPLOYEE |
3 | >A1.run(Employees=A2.select(month(BIRTHDAY)==A1.ID)) |
In A3, assign the null-value field Employees with the records of employees born in each month. Once executed, the TSeq in A1 is as follows:
In fact, the result of grouping an RSeq is just a sequence composed of sets. It is similar to the field referencing single sets. For example, if grouped by the birth month of employee, the code is:
A | |
1 | $ select EID,NAME+’ ‘+SURNAME FULLNAME, BIRTHDAY from EMPLOYEE |
2 | =A1.group(month(BIRTHDAY)) |
The grouping result is as follows:
Like the result in the above example, the result of grouping can be further used in various computations if necessary:
A | |
1 | $ select EID,NAME+’ ‘+SURNAME FULLNAME, BIRTHDAY from EMPLOYEE |
2 | =A1.group(month(BIRTHDAY)) |
3 | =A2.new(#:Month,~.count():Count) |
4 | =A2.new(#:Month,~.minp(BIRTHDAY).FULLNAME:Oldest) |
In A3, count the total number of employees who were born in each month. The oldest employees born in each month are listed in A4. Once executed, A3 and A4 get the following results: