Before we take a look at what MBS can do with SQL, let's take a look at FileMaker's own functions and get started with the SQL language. In today's example, we are working with a table listing Christmas movies. It is called Movie and has the following fields: Name, Director, Year and Generated_Sales. The first queries will be run on this table in a moment.

Important terms in the SQL language are SELECT FROM and WHERE. These are based on the English language, making it relatively easy to understand what a statement does. If we want to get the data from a specific field, we can write SELECT followed by the name of the field from which we want the data. SQL is layout-independent and does not automatically know from which table we want the data; we have to specify this in the FROM part. So we write FROM and then the table name. If we want to use SQL to query all movie names that are available in the Movie table, the query looks like this:
SELECT Name FROM Movie
We can use this query right away in the ExecuteSQL function in FileMaker. We should not mix up this function with the Execute SQL script step, because that one isn't meant for working on our FileMaker database, but for accessing an external database. Let's now turn to the ExecuteSQL function and take a look at its structure.
ExecuteSQL ( sqlQuery ; fieldSeparator ; rowSeparator { ; arguments... } )
We see several parameters that need to be filled in. First, we have the parameter for the SQL statement, where we can enter the SQL expression we have already determined. Then we have the field separators. We can not only retrieve data from one field, as in this example, but also from several fields. These fields must then be separated from each other in the result text. We can choose this separator here; in our example, we use a space. However, there is not only a field separator, but also a separator between the individual data records. In our example, we choose a line break to separate the data records from each other. Optionally, you can also work with arguments in the function. We will come to these later.
If we now insert the SQL query and other parameters into the function, it looks like this:
Set Variable [ $Text ; Value: ExecuteSQL ( "SELECT Name FROM Movie" ; " " ; "¶" ) ]
The result we get is text that we can then reuse, e.g., as shown here in a dialog box for output.

We have already mentioned that we can return not just one field in the result, but several. If you do not want to select specific fields, you can also return all fields. To do this, you do not need to write all field names one after the other; instead, you can place an * after SELECT.
Set Variable [ $Text ; Value: ExecuteSQL ( "SELECT * FROM Movie" ; ", " ; "¶" ) ]
This time, we have used a comma as the field separator.

As you can see, the output also displays fields that are not on the layout. This behavior once again highlights the independence from the layout.
If we want data from multiple fields, we must separate them with a comma in the SELECT part. In this example, we have the name of the movie and the director. This time, the fields are separated by a hyphen.
Set Variable [ $Text ; Value: ExecuteSQL( "SELECT Name, Director FROM Movie" ; "-" ; "¶" ) ]

Let's try this with the name and year:
Set Variable [ $Text ; Value: ExecuteSQL( "SELECT Name, Year FROM Movie" ; "-" ; "¶" ) ]
Now it gets strange, because we get a question mark back instead of the movies with the corresponding years. The question mark is displayed when the function has not produced a reasonable result. There was an error. However, we cannot determine where the error occurred with this function. For this, we need the ExecuteSQLe function, which returns an error text in addition to the question mark in case of errors. The parameters of the function are the same.
Set Variable [ $Text ; Value: ExecuteSQLe( "SELECT Name, Year FROM Movie" ; "-" ; "¶" ) ]

Based on the error message, we can now see that the problem lies with the field name Year, as this is the same name as a FileMaker function and this causes a conflict. We can easily solve the problem by changing the field name and repeating the query with the changed field name.
In SQL, we not only want to retrieve data on all records for different fields, but as we already indicated yesterday, data can also be filtered, and we can use this to formulate searches in our database in SQL style. An important key to this is the WHERE clause. Here, we can specify what our data must have in common in order for it to be included in the result set. For example, we can search for all films made by a specific director. To do this, we first specify the fields we want to display in the SELECT part, as we did before. In the FROM part, we then specify the table name from which the data comes. Now comes the new part, the WHERE part. Here, we query the director named Chris Columbus. Since this is text, we enclose the name in single quotation marks. The SQL statement then looks like this:
SELECT Name, Launch FROM Movie WHERE Director = 'Chris Columbus'
However, we can not only search for equal values, but also for values that are smaller or larger. For example, we can list all films made after 2015 by placing Launch>2015 in the WHERE section. Now, it may happen that we get a question mark as a return value in the output. Why is that? If we have defined our Launch field as text, the text cannot be compared with greater than or less than. For this reason, we must ensure that the field has the correct data type. Then our query will work.

As in the IF statements in FileMaker, we can also specify conditions with AND, OR, and NOT here. This allows us to link multiple conditions for our data and define more specific search queries. In the next query, we want all movies directed by Chris Columbus, plus movies released in 2000 that were not directed by Greg Beeman.
Such a query would look like this:
Set Variable [ $Text ; Value: ExecuteSQL( „SELECT Name, Launch FROM Movie WHERE Director = 'Chris Columbus' OR Launch=2000 AND NOT Director='Greg Beeman'" ; "-" ; "¶" ) ]

We already mentioned that FileMaker has arguments. These arguments are a bit like placeholders for values that we want to use in our SQL statement. This allows us to specify the name of the director as an argument. In the query text, we then insert a question mark instead of the value. It might look like this:
Set Variable [ $Text ; Value: ExecuteSQL( "SELECT Name, Launch FROM Movie WHERE Director = ?" ; "-" ; "¶";"Chris Columbus" ) ]
The output is exactly the same. But on the one hand, we have made the query more maintainable and can save ourselves the typing for concatenating values if the specified value is a variable. But probably the most important reason for using these arguments is that we have more security because we can avoid SQL injection. Let's assume we want to give the user free input and define our query as follows:
Set Variable [ $Text ; Value: ExecuteSQL( "SELECT Name, Launch FROM Movie WHERE Director ='" & $Test&"'" ; "-" ; "¶" ) ]
The variable Test contains what we got back from the user input. Ideally, this is the name of a director. But and this is the crux of the matter — theoretically, the user could also enter SQL commands and thus retrieve information that they should not have access to. For example, if the user enters the following:
Chris Columbus' OR NOT Director='Chris Columbus
Set Variable [ $Test ; Value: "Chris Columbus' OR NOT Director='Chris Columbus" ] Set Variable [ $Text ; Value: ExecuteSQL( "SELECT Name, Launch FROM Movie WHERE Director ='" & $Test & "'"; "-" ; "¶" ) ]

Then this is an input that is accepted, since we have also set the appropriate quotation marks, and all data is then displayed because the query is correct for all data records.
Of course, we want to avoid this, as it could cause much more potential damage. And for this purpose, we have our arguments that make the whole thing a prepared statement, which we read as formatted text and not as an instruction.
Set Variable [ $Text ; Value: ExecuteSQL( "SELECT Name, Launch FROM Movie WHERE Director = ?" ; "-" ; "¶";"$Test" ) ]

That brings us to the end of today's door, and I look forward to welcoming you back tomorrow.