On this page, I'll focus on Jet's SQL dialect and show you what you can do with SQL (almost everything), what you can't do with Jet SQL (there are several key things that can't be done), and where SQL works better than Jet Data Access Objects for working with a database. If you need a little background on building databases, you may wish to pay a visit to my Introduction to the Relational Database Model page or my Fundamentals of Database Design page.
The Visual Basic and Access help files provide fairly complete instructions for using SQL statements. (Assuming you know what statements you want to use.) In fact, most of the content on this page is based directly on information available in the help files. Hopefully, I've organized it in a way that makes it a little easier to understand.
Introduction to Jet SQL |
If you desperately want to avoid dealing with DAO code, you can "cheat" and just use the Database property of the lowly data control. I don't recommend this for any real production code however, since you'll be replacing about five lines of DAO code with a hefty custom control.Unlike Jet Data Access Objects, SQL makes a clear distinction between the language used to create database objects (Data Definition Language or DDL) and the language used to manipulate data (Data Management Language or DML). In the next two sections, we'll look at SQL for creating a database and working with data.
In all of the code examples, I'll be using a database object - db - that's assumed to be created elsewhere. Keep this in mind when you see the statement db.Execute. I'm also going to operate under the assumption that you have the good sense to name all of your database objects with names that don't require you to use square brackets everywhere. An easy rule is to give objects names that would be valid identifiers in Basic code. Jet limits the length of most identifiers to 64 characters, but you should try to use much less. (If you think you might ever upsize to SQL Server, use identifiers of 30 characters or less).
Constructing a Database with SQL |
CREATE TABLE tablename
(
fieldname type [size] [CONSTRAINT],
fieldname type [size],
[CONSTRAINT]
)
Let's first break that down a little and explain the components in plain English.
Let's look at a simple example before examining how to create each type of field:
CREATE TABLE Customers
(
CustID COUNTER
CONSTRAINT pkCustomers PRIMARY KEY,
CustFirstName TEXT 25,
CustLastName TEXT 25,
CustAddress TEXT 100,
CustCity TEXT 50,
CustState TEXT 2,
CustZIP TEXT 10,
CustPhone TEXT 14
)
The final step for this in an application would be to actually have Jet execute the SQL statement. This
is done using the Execute method of the Database object. In the code sample, you can assume that the
variable sSQLCreateTable is a string variable which has been assigned the above SQL statement. Here's
the necessary DAO code:
On Error Resume Next
db.Execute sSQLCreateTable, dbFailOnError
If Err Then
' failed - handle error
Else
' succeeded
End If
That's it! Essentially, only two lines of code are going to do the entire task using a SQL CREATE TABLE
statement: one (or more) to assign the SQL statement to a string variable, and one to call the Execute method.
If you're feeling daring, you can even enter the SQL statement as a literal string in the Execute method
(although I wouldn't recommend it for debugging purposes).
IMHO, using a SQL statement and the Execute method is a considerably simpler method of creating a table than using the DAO library. Using straight DAO code, you would need to call CreateTableDef to get a reference to a TableDef object, then repeatedly call CreateField for each field, using the Append method to add the fields to the table and finally using the Append method to add the TableDef to the database's TableDefs collection. However, there are some things (most unfortunately) that you can't create using the SQL CREATE TABLE statement, so you might need the DAO code anyway. If you need to set properties such as the default value, validation rule, etc., some DAO code will be necessary, but you might find it easier to create the basic table structure using a SQL statement then just set the extra properties with DAO since at that point the TableDef object and all the Field objects will already exist.
| Data Type | Keyword | Storage Size (bytes) | Description |
| Binary | BINARY | 1 | For queries on attached tables from database products that define a Binary data type. |
| Boolean | BIT | 1 | True or False values. Note that although the data type is BIT, the storage size is one byte. Additionally, BIT values cannot be Null in a Jet database. |
| 1 Byte Integer | BYTE | 1 | An integer value between 0 and 255. |
| Autoincrement Field | COUNTER | 4 | A number automatically incremented by the Jet engine whenever a new record is added to a table. In the Jet engine, the data type for this value is a Long. |
| Financial Values | CURRENCY | 8 | A scaled integer between -922,337,203,685,477.5808 and 922,337,203,685,477.5807. You should always use the CURRENCY data type when dealing with money for greater accuracy in doing financial calculations. (Don't use floating point data.) |
| Dates | DATETIME | 8 | A date or time value between the years 100 and 9999. Keep in mind that the current calendar hasn't been in use forever, so don't assume you can do legitimate date math going back to the year 100. |
| Single Precision Floating Point | SINGLE | 4 | A single-precision floating-point value with a range of -3.402823E38 to -1.401298E-45 for negative values, 1.401298E-45 to 3.402823E38 for positive values, and 0. |
| Double Precision Floating Point | DOUBLE | 8 | A double-precision floating-point value with a range of -1.79769313486232E308 to -4.94065645841247E-324 for negative values, 4.94065645841247E-324 to 1.79769313486232E308 for positive values, and 0. |
| 2 Byte Integer | SHORT | 2 | A short integer between -32,768 and 32,767. |
| 4 Byte Integer | LONG | 4 | A long integer between -2,147,483,648 and 2,147,483,647. Note that this is also the data type of the counter field. |
| Text | LONGTEXT | 1 byte per character | Used for long text strings up to a maximum of 1.2 gigabytes. (Don't use this data type if you can get by with the 255 character limit of the normal TEXT data type. The TEXT data type is significantly faster for Jet to retrieve.) This field type is called a Memo in Access. |
| Binary | LONGBINARY | As required. | Zero to a maximum of approximately 1 gigabyte. Used for OLE objects. |
| Text | TEXT | 1 byte per character | Zero to 255 characters. You must specify the size of the field when creating a TEXT field, but the size you specify is a maximum allowable size. Jet always stores text data as variable length strings. (This data type offers much better performance than the LONGTEXT type. If you can fit the data in 255 characters or less, don't use LONGTEXT.) |
Perhaps you noticed that this table is nearly identical to the help file. If you didn't, searh the VB help file for the topic "Microsoft Jet Database Engine SQL Data Types".
Single Column Constraint
CREATE TABLE Customers
(
CustID COUNTER
CONSTRAINT pkCustomers PRIMARY KEY,
CustName TEXT 25,
...
)
Mulitple Column Constraint
CREATE TABLE BookAuthors
(
BABookID LONG,
BAAuthorID LONG,
CONSTRAINT pkBookAuthors PRIMARY KEY
(BABookID, BAAuthorID)
)
There are three types of constraints you can create:
Let's take a look at creating a foreign key constraint by expanding on the previous definition of the BookAuthors table. The foreign key is specified by using the REFERENCES keyword. In this case, we are enforcing the BABookID key against the primary key of the Books table and enforcing the BAAuthorID key against the primary key of the Authors table.
Single Column Foreign Key Constraint
CREATE TABLE BookAuthors
(
BABookID LONG
CONSTRAINT fkBABookID
REFERENCES Books (BookID),
BAAuthorID LONG
CONSTRAINT fkBAAuthorID
REFERENCES Authors (AuthorID),
CONSTRAINT pkBookAuthors PRIMARY KEY
(BABookID, BAAuthorID)
)
It's also possible to create a multiple column foreign key. Here we will reference the two
column primary key of the BookAuthors table.
Multiple Column Foreign Key Constraint
CREATE TABLE PublishedAuthors
(
PABookID LONG,
PAAuthorID LONG,
PAPubID LONG
CONSTRAINT fkPAPubID
REFERENCES Publishers (PubID),
CONSTRAINT pkPublishedAuthors PRIMARY KEY
(PABookID, PAAuthorID, PAPubID),
CONSTRAINT fkPABookAuthors
FOREIGN KEY (PABookID, PAAuthorID)
REFERENCES BookAuthors (BABookID, BAAuthorID)
)
One of the things I like about using SQL (or even DAO) to create relationships is that you can give the foreign key constraint a meaningful name. Although you may never need to refer to the name of the constraint in code, if you do its nice not to have to deal with a name like "Reference86" that Access creates when you use the Relationships window.
ALTER TABLE tablename
{ADD {COLUMN field type[(size)] [CONSTRAINT index]
CONSTRAINT multifieldindex} |
DROP {COLUMN field | CONSTRAINT indexname} }
The syntax which follows ADD COLUMN or ADD CONSTRAINT is identical to that used for
the CREATE TABLE statement. Its essentially the same as CREATE TABLE with the
exception of the ADD keyword.
I hate to have to put it this way, but if you can't figure the rest of adding a field or constraint on your own, either reread the CREATE TABLE section, consult the help files, or give up in disgrace. :-)Let's look at one of the previous examples and drop a column we created earlier:
ALTER TABLE Customers DROP COLUMN CustNameNow we'll drop a constraint:
ALTER TABLE BookAuthors DROP CONSTRAINT fkBAAuthorIDAs you can see, SQL makes it almost dangerously easy to delete elements of a database structure. We'll look at some other things you can do with the DROP keyword later in the section on the DROP statement.
Just in case you didn't read the little note above, I'll be thorough in my examples and restore the column and constraint I just dropped.
ALTER TABLE Customers ADD COLUMN CustName TEXT 25 ALTER TABLE BookAuthors ADD CONSTRAINT fkBAAuthorID FOREIGN KEY (BAAuthorID) REFERENCES Authors (AuthorID)
Here's the general syntax:
CREATE [ UNIQUE ] INDEX indexname
ON tablename
(fieldname [ASC|DESC][, fieldname [ASC|DESC], ...])
[WITH { PRIMARY | DISALLOW NULL | IGNORE NULL }]
Here's a few things you can do with CREATE INDEX that aren't available with the
CONSTRAINT clause.
CREATE TABLE Customers
(
CustID LONG,
CustCompanyID LONG
CONSTRAINT fkCustCompanyID
REFERENCES Companies (CompanyID),
CustFirst TEXT 25,
CustMiddle TEXT 25,
CustLast TEXT 25,
CustCity TEXT 50,
CustState TEXT 2,
CustZIPCode TEXT 10,
CustPhone TEXT 14,
CustSSN TEXT 11
)
First we'll create the primary key for the table:
CREATE INDEX pkCustomers ON Customers (CustID) WITH PRIMARYNext, we'll index the foreign key to the Companies table and disallow nulls so that the value will be required in the table.
CREATE INDEX idxCustCompanyID ON Customers (CustCompanyID) WITH DISALLOW NULLSince we'll often be sorting the data on the name, we'll create a multi-column index on the first, middle and last names. Since there may be records with null values in one or more of the columns, we'll ingore nulls in the index.
CREATE INDEX idxCustName ON Customers (CustLast, CustFirst, CustMiddle) WITH INGORE NULLFinally, we'll create a unique index on the social security number column. (This column would also be a candidate for a primary key since it must be unique for each entry.)
Database theory purists would probably take issue with the statement that the social security number is guaranteed to be unique. I'll leave that discussion to the newsgroups and chat rooms. For now, I'll only state that, IMHO, it's always best to use an arbitrary value for a primary key column.
CREATE UNIQUE INDEX idxCustSSN ON Customers (CustSSN) WITH DISALLOW NULL
A column such as this which is both a required entry and required to be unique, but not the primary key for the table, is sometimes referred to as an alternate key.That's all there is to creating indexes on tables.
Here's the general syntax for using DROP:
DROP {TABLE table | INDEX index ON table}
It doesn't get any easier than this with SQL. Let's delete the Customers table we
created earlier.
DROP TABLE CustomersNow lets drop the idxCustName index we created on the Customers table (imagine for the moment that we haven't already dropped the Customers table itself).
DROP INDEX idxCustName ON CustomersAs you can see, the DROP statement is exceedingly simple - almost dangerously simple. When using the DROP statement - especially with a production database - remember that there's no such thing as an "undelete" function.
Querying the Database with SQL |
SELECT [predicate] { * | table.* | [table.]field1 [, [table.]field2[, ...]]}
[AS alias1 [, alias2 [, ...]]]
FROM tableexpression [, ...] [IN externaldatabase]
[WHERE... ]
[GROUP BY... ]
[HAVING... ]
[ORDER BY... ]
[WITH OWNERACCESS OPTION]
Let's break down some of the components of the SELECT statement.
Understanding the construction of a SELECT query is vital to being able to build a database
application. Even if you use the Access query design window to build most of the queries in
your application, you may still need to create a query "on-the-fly" in code. While you can
"cheat" and use the Access query designer for most of the work, you'll still need to
understand the fundamentals of the SELECT statement to build the SQL string.
Using the Access query designer isn't really cheating - I do it all the time. You can save yourself a considerable amount of development effort by using this tool. However, you need to understand that the query designer is really just a nice user interface for building a SELECT statement.For most SELECT queries, the key areas you'll need to understand are the field list, FROM clause, and WHERE clause. The GROUP BY and HAVING clauses are used for totals queries, often with aggregate functions. Use the ORDER BY clause to sort the data in the query.
SELECT CustID, CustFirst, CustLast FROM CustomersThere are several additional options that are available:
You can create inner joins using the where clause of a SQL statement, but you must use the RIGHT JOIN or LEFT JOIN syntax to create outer joins.
table1 INNER JOIN table2 ON table1.field = table2.field
Jet requires that you fully qualify the field names in the ON clause of inner and outer joins even if both field names are unique in the query. If you don't use the full table.field form, you'll get a syntax error from Jet.With inner joins only, you can also use the WHERE clause of a SELECT query to create a join, although the Jet documentation recommends using the INNER JOIN syntax. Here's what an inner join looks like when using the WHERE clause:
SELECT CustID, CustFirst, CustLast, CompanyID, CompanyName FROM Customers, Companies WHERE CustCompanyID = CompanyID
Oddly enough, you do not need to use the fully qualified field names when creating a join in a where clause. Additionally, if you should happen to forget the WHERE clause with this syntax, you'll get a Cartesian product. If the tables are large, the query could run endlessly.
Return all records from Companies and only matching records from Employees:
SELECT * FROM Companies LEFT JOIN Employees ON Companies.CompanyID = Employees.EmpCompanyID ...or... SELECT * FROM Employees RIGHT JOIN Companies ON Employees.EmpCompanyID = Companies.CompanyIDCertain types of outer joins cannot be resolved by Jet. The following diagram illustrates two outer join constructions that will fail:
| Outer Join Constructions |
![]() |
There may be other outer joins which are not supported, but these are the only ones I've encountered. Don't feel too frustrated by this limitation, however - Jet is much more flexible with outer joins than most database engines.
SELECT * FROM Customers IN "F:\dbfiles\custdb.mdb"Several other database formats are supported, including dBase, Paradox, and Btrieve. For the syntax, search the VB help files for the keywords "IN clause".
If you're using Access, you can make data from tables available without having the tables appear in the database window by creating a query and using an IN clause to specify another database file. However, if you do this you should keep in mind the fact that you're distributing the path to the external database throughout your SQL instead of consolidating it in the Connect property of attached tables. In a large database, this could be a maintenance nightmare.
field comparisonoperator value
Note: A WHERE clause can contain up to 40 expressions linked by logical operators, such as And and Or.Let's look at each of the components:
| Data Type | Jet Field Data Types | Delimiter | Example |
| Numeric |
Long Integer Integer Byte Single Double Currency |
No delimiter | CustID = 1 |
| Text |
Text Memo |
Quoted |
CustLast = 'Garrick'
Note: Jet allows the use of either single or double quotes. For the best compatibility with other database engines, you should stick with using single quotes. Also note that if the value contains a single quote, you need to replace it with two single quotes. (You may wish to write a simple procedure to replace all instances of a single quote in a string with two single quotes.) |
| Date | DateTime | Pound Sign (#) |
OrdDate = #1/1/1980#
Note: If you're planning to eventually upsize a Jet database to SQL Server, date comparisons in SQL strings may be a problem since SQL Server uses single quotes as date delimiters. Here again, a small procedure that builds the appropriate string may be useful. Also note that regardless of your international settings, you must always use the U.S. date formats mm/dd/yy or mm/dd/yyyy. |
| Boolean |
Yes/No Any integer type |
N/A, use the True keyword |
CustIsApproved = True Note: You can use true with any numeric field or a Yes/No (Boolean) field. Like Visual Basic in general, Jet treats any non-zero value as True and zero as False. If you look at a Yes/No column in an Access datasheet, you'll see that, also like VB, Jet stores -1 for True. Don't, however, compare to -1, use the True keyword. |
| Nulls | All | N/A, use IS NULL |
CustAddress IS NULL Note: See below under Comparison Operators for more on Nulls |
If, for example, you have a table of orders, and you want to get the total number of orders for each particular item, a SELECT query with a GROUP BY clause might look like this:
SELECT Count(*) AS TotalOrders, OrdItem FROM Orders GROUP BY OrdItem;This query will generate one record for each unique value in the OrdItem column. The TotalOrders column in the query will show the number of records in the table for each different value in the OrdItem column.
Continuing with the previous example, the HAVING clause can be used to restrict the results in a manner different from what can be done with a WHERE clause. If the list of possible values in the OrdItem column are Wheel, Tire, Axle, Bearing, and Spoke, you could use a WHERE clause to restrict the query to a subset of all possible values:
SELECT Count(*) AS TotalOrders, OrdItem FROM Orders WHERE OrdItem = 'Wheel' Or OrdItem = 'Axel' GROUP BY OrdItem;A HAVING clause, on the other hand, could restrict the results to only those items with over a specific number of orders:
SELECT Count(*) AS TotalOrders, OrdItem FROM Orders GROUP BY OrdItem HAVING Count(*) > 100;This would return one record for each of the available values in OrdItems only if there were more than 100 orders for that item.
ORDER BY field1 [ASC | DESC ][, field2 [ASC | DESC ][, ...]]You can specify more than one field. If there are multiple fields specified, the results will be sorted by the first field listed, then by the second field in cases where the values in the first field are equal, and so on. By default, records are sorted in ascending order (a-z, 0-9), but you can explicitly specify an ascending or descending sort with the ASC or DESC keywords.
Remember that if no ORDER BY clause is present, records are unsorted. Normally, they will appear in the order they are entered, but you cannot rely on a specific sort order unless you include an ORDER BY clause.
The ORDER BY clause is normally the last clause in a SELECT query.
| ALL | The ALL predicate returns all records that meet the conditions in the SELECT statement. It is not necessary to specify ALL in a SELECT statement because ALL is assumed if no predicate is specified. |
| DISTINCT |
DISTINCT omits records that have duplicate data in the selected fields. For example, the following
SELECT statement:
SELECT DISTINCT CustLast FROM Customers;
...will return one record for each unique value in the CustLast field. The behavior of the
DISTINCT predicate is similar to using a GROUP BY clause.
Note: Using DISTINCT will make the results of the query non-updatable. |
| DISTINCTROW |
The DISTINCTROW predicate omits data based on entire duplicate records, not just duplicate fields.
DISTINCTROW is useful only when the SELECT query includes more than one table, but you are only
returning fields from one table. If only one table is included in the query, or you include fields
from all tables, DISTINCTROW is not useful.
SELECT DISTINCTROW CustName
FROM Customers INNER JOIN Orders ON Customers.CustID = Orders.OrdCustID
WHERE OrdTotal > 100
ORDER BY CustName;
This query will return a unique list of the customers who have orders totaling over $100.00. Since
each customer can have many orders, the DISTINCTROW keyword eliminates the duplicate values.
Note: Using DISTINCTROW will make the results of the query non-updatable. |
| TOP |
The TOP keyword is used to restrict the results to a fixed number of records or a percentage of
the total qualifying records in the results. For, example, to return the top 10 states by
population, you would use:
SELECT TOP 10 StateName FROM States ORDER BY StatePopulation;
Continuing with the same example, you could also return the top 25% of states by population:
SELECT TOP 25 PERCENT StateName FROM States ORDER BY StatePopulation;
While there is no BOTTOM keyword, you can achieve the same result by changing the ORDER BY clause:
SELECT TOP 25 PERCENT StateName FROM States ORDER BY StatePopulation DESC;
Note: Using TOP doesn't affect the updatability of the results of a SELECT query.
|
If, for example, you have a table of employee information that includes name, phone, and salary information, you may wish to restrict access to the table so that only managers can see the salary data. Using the security system, you can restrict the read data permission to only the managers. However, you may wish to allow all users to see the name and phone information. By using the WITH OWNERACCESS OPTION clause, you can allow all users to see a subset of the data by building a query as follows:
SELECT EmpName, EmpPhone FROM Employees WITH OWNERACCESS OPTION;Anyone with read data permission on this query will be able to see the name and phone but not the salary, regardless of their underlying permission on the Employees table.
WITH OWNERACCESS OPTION is only useful when working with a saved query definition (as opposed to a dynamically generated SQL statement) in a secured, multiuser environment.
Managing Data with SQL |
Note: Access adds a little confusion to these SQL operations by referring to an INSERT statement as an Append query and a SELECT INTO statement as a Make-Table query. Maybe its just me, but I don't find the word "append" any more obvious than "insert". At least they left update and delete intact. All of these query types are known collectively as action queries.
All of the action queries are run in code using the Execute method of a database object. If you're building database applications using the data control, you probably won't be using these query types often. However, if you're using unbound data, INSERT, UPDATE, and DELETE queries will be as common as SELECT queries in your application.
Insert records into a destination table from a source table (or tables):
INSERT INTO destination [IN externaldatabase] [(field1[, field2[, ...]])] SELECT [source.]field1[, field2[, ...] FROM sourceInsert a new record based on fixed values:
INSERT INTO destination [(field1[, field2[, ...]])] VALUES (value1[, value2[, ...])
Let's say we have two tables, Customers and Prospects which have identical field lists. Instead of working with two tables we decide to combine them into a single table with a Type field that identifies the type of person as a customer or a prospect. Here's the SQL statement:
INSERT INTO Customers (CustID, CustType, CustName, CustPhone) SELECT ProspectID, "Prospect" As CustType, ProspectName, ProspectPhone FROM Prospects;Note: The Visual Basic help file topic for the INSERT INTO statement incorrectly states that if the table you are copying from has a counter field that you should not include the counter in the query. The fact is that you can include the counter field if the values don't violate the primary key in the destination table.
You may want to do this in a situation where you have a relationship defined with the source table and you would like to preserve the links to records in other tables. Here's one way to do this (this assumes that there are values in the source table that would violate the foreign key in the destination table and that both keys are counter fields - note also that this will not necessarily work if you're using random instead of incrementing counters with Jet 3.x):
INSERT INTO Customers (CustFirst, CustLast)
VALUES ("Joe", "Garrick");
Using an INSERT INTO statement with the Execute method of the Database object is probably the fastest
method of adding a record to a table, but there are two problems with it:
UPDATE table SET field = value WHERE criteriaThe UPDATE statement will modify all records matching the criteria specified by the WHERE clause.
Note: It's particularly important to make sure you get the WHERE clause correct in an UPDATE statement. If, for example, you accidentally omitted the WHERE clause you would modify all of the records in the table.There's no difference in the syntax for an UPDATE statement that modifies one record or several records - the WHERE clause controls which records are modified. Let's look at an example. Here we will "upgrade" the skill level of some programmers:
Here we'll update a single record (assume that PgmrID is the primary key):
UPDATE Programmers SET PgmrSkill = 'Intermediate' WHERE PgmrID = 10;Here we'll change all of the newbies to intermediates:
UPDATE Programmers SET PgmrSkill = 'Intermediate' WHERE PgmrSkill = 'Newbie'And finally here we'll just make them all experts:
UPDATE Programmers SET PgmrSkill = 'Guru'You can also update multiple fields in a single UPDATE statement. Let's upgrade programmer 10 again:
UPDATE Programmers SET PgmrSkill = 'Veteran', PgmrStyle = 'Clear' WHERE PgmrID = 10;This also works with bulk updates:
UPDATE Programmers SET PgmrSkill = 'Newbie' PgmrStyle = 'Cryptic' WHERE PgmrYearsExperience = 0;The UPDATE statement is a very efficient method of modifying data in a table. Since you already know how to restrict the records via the WHERE clause, you don't have the problems of determining a primary key that you have with the INSERT INTO statement. In most cases, an UPDATE statement should provide much better performance than using a Recordset object and the Edit and Update methods.
DELETE table.* FROM tableexpression WHERE criteriaThe first part, table.*, is optional. If you are deleting records based on a selection that does not include joins, you can simply specify:
DELETE FROM table WHERE criteriaThe FROM and WHERE clauses are identical to those you would build for a SELECT statement. Let's delete some of the programmers we modified above:
DELETE FROM Programmers WHERE PgmrSkill = 'Newbie';When used with a multiple table expression, you can base the criteria on fields from a table other than the one where the records will be deleted.
DELETE Programmers.* FROM Programmers INNER JOIN ProjectProgrammers ON Programmers.PgmrID = ProjectProgrammers.PPPgmrID WHERE ProjectProgrammers.PPProjectID = 10;Here we have deleted all programmers associated with project 10.
There are a few additional things to keep in mind when using a DELETE statement:
SELECT field0, field1 INTO newtable IN externaldatabase FROM tableexpressionBy this point, you should already have a pretty good idea what the components of the this SQL statement do. Following the keyword SELECT is a field list. After INTO comes the name of the new table to be created. The IN clause can optionally be used to specify a database other than the current database as the destination. The FROM clause is a standard SQL FROM clause and can include joins, criteria, and so on.
Here is a simple example that will make a new table from a subset of a Customers table:
SELECT CustID, CustFirst, CustLast INTO CustomersWithOrders FROM Customers INNER JOIN Orders ON Customers.CustID = Orders.OrdCustID;There are a few points to keep in mind when using SELECT...INTO:
Limitations of Jet SQL |
Summary |
Let's review some of the key points:
Originally written by Joe Garrick
doubt
i need coding for dns connection.
I connect dns_name="sal" but forgot conding
NEED HELP...
can you help me with this ....
we have a table:Medrep,assign,doctors,
table medrep attributes : medrepID,Fname,Lname
table doctors attributes : docID,Fname,Lname
table assign attributes : docID,medrepID
the relationship of the medrep asign a doctors is many-to-many relationship,
and i have a input textbox that allow the user to input the Lname of the medrep..
my question is..i need to display all the Lname of the table doctor where the medrep medrepID equals assign medrepID and doctor docID not equals to the assign docID where the medrep Lname is equal to the inputed Lname..
i try many method but always failed..
i need the sql statement..
my instructors said i just need to user Inner Join and Outer Join...
i need the sql statement...
just email the sql statement..
thanks in advance...
VB6 SQL Insert with strings
I have always fought inserting into a table a new record if any value contains a
date or string.
The first of the following INSERT statements works perfectly.
The 2nd and 3rd INSERT statements fail with a "Syntax" error but of course MS
does not elaborate as to why it failed.
The 2nd INSERT is exactly the same as the first with one text field and
associated string value added "Note" with a value of 'N/A'
I tried removing Note and adding "Date" with the same error.
NOTE: The text field "FromTo" does work with a value of 'test 11'
Grrrrrrrrrrrrrrrrrrrrrrrr!
Any help would be greatly appreciated.
Debug.Print results shown below:
WORKS PERFECTLY
INSERT INTO tblCheckingMaster (CheckNum, FromTo, Amount, PostedYN, DepositYN,
InterestDepositYN, RunningBalance) Values (1011, 'test 11', 11, True, False,
False, 15062.64)
INSERT INTO tblCheckingMaster (CheckNum, FromTo, Amount, PostedYN, DepositYN,
InterestDepositYN, RunningBalance, Note) Values (1012, 'test 12', 12, True,
False, False, 15061.64, 'N/A')
FAILS with [Microsoft][ODBC Microsoft Access Driver] Syntax Error in INSERT INTO Statement
INSERT INTO tblCheckingMaster (CheckNum, FromTo, Amount, PostedYN, DepositYN,
InterestDepositYN, RunningBalance, Date) Values (1012, 'test 12', 12, True,
False, False, 15061.64, '12/5/2010')
FAILS with [Microsoft][ODBC Microsoft Access Driver] Syntax Error in INSERT INTO Statement
s
I didnt like
eheres the vb6 code?
Between function
Example #2 - Dates
You can also use the BETWEEN function with dates.
SELECT *
FROM orders
WHERE order_date between to_date ('2003/01/01', 'yyyy/mm/dd')
AND to_date ('2003/12/31', 'yyyy/mm/dd');
This SQL statement would return all orders where the order_date is between Jan 1, 2003 and Dec 31, 2003 (inclusive).
It would be equivalent to the following SQL statement:
SELECT *
FROM orders
WHERE order_date >= to_date('2003/01/01', 'yyyy/mm/dd')
AND order_date <= to_date('2003/12/31','yyyy/mm/dd');
Please help me!!
Hello mr.Aamir Abbas ^^
I have some questions about your 'between function' post.... please help with your answer...
I have tried 'to_date' statement but computer said 'undeclared function' ????? what must i do ???
i want to bind records like your example, but the records that appear are not precise, some records those have date not in my between statement are also returned.... whats wrong????
Thanks.
Post new comment