Create a check constraint in access and/or DAO - vba

I am trying to create a check constraint on an access (jet?) table.
So, I open the .mdb file with access, go into queries->create query in design view,
type esc, then menu->view->query and finally type
create table X (
a number,
check (a > 20)
)
but access thinks that I have a "syntax error in field definition". However, I don't think so. Therefore my question: is it possible to create a check constraint with access. If so: how.
Additionally, I'd like to create the constraint with dao/vba, not on the GUI. Is that possible?
And lastly, on a slightly related note: how do you enter sql statements into access. I can't imagine that I have to use the queries->design view->query->view route in order to do that. I am used to Oracle's SQL*Plus, which I like very much, and I'd hope there's something similar for access as well.
Thanks for any input
Rene

Here are some notes.
You can create a Pass-Through query for Oracle (Select menu "Query" > "SQL Specific" > "Pass-Through")
Since Access 2003, you can select SQL Server Compatible Syntax (ANSI 92) (http://office.microsoft.com/en-us/access/HA010345621033.aspx)
A validation rule with VBA / DAO
''Reference: Microsoft DAO x.x Object Library
Dim tdf As TableDef
Dim db As Database
Set db = CurrentDb
Set tdf = db.TableDefs("Table1")
tdf.Fields("aDouble").ValidationRule = "<10"
tdf.Fields("aDouble").ValidationText = "Must be less than 10"
Constraints with ADO / VBA. See [Intermediate Microsoft Jet SQL for Access 2000](http://msdn.microsoft.com/en-us/library/aa140015(office.10).aspx)
''Reference: Microsoft ADO Ext. x.x for DDL and Security
Dim cn As ADODB.Connection 'For action queries
Dim rs As ADODB.Recordset 'For select queries
Dim s As String
Dim RecordsAffected As Long
Set cn = CurrentProject.Connection
''You can store sql in a table
s = DLookup("SQLText", "sysSQL", "ObjectName='q1'")
''Result: CREATE TABLE tblCreditLimit (LIMIT DOUBLE)
cn.Execute s, RecordsAffected
Debug.Print RecordsAffected
''You can run queries from VBA
s = "INSERT INTO tblCreditLimit VALUES (100)"
cn.Execute s, RecordsAffected
Debug.Print RecordsAffected
s = "CREATE TABLE tblCustomers (CustomerID COUNTER, CustomerName Text(50))"
cn.Execute s, RecordsAffected
Debug.Print RecordsAffected
s = "INSERT INTO tblCustomers VALUES (1, 'ABC Co')"
cn.Execute s, RecordsAffected
Debug.Print RecordsAffected
s = "ALTER TABLE tblCustomers " _
& "ADD COLUMN CustomerLimit DOUBLE"
cn.Execute s, RecordsAffected
Debug.Print RecordsAffected
''You can add contraints using ADO like so:
s = "ALTER TABLE tblCustomers " _
& "ADD CONSTRAINT LimitRule " _
& "CHECK (CustomerLimit <= (SELECT LIMIT " _
& "FROM tblCreditLimit))"
cn.Execute s, RecordsAffected
Debug.Print RecordsAffected
s = "UPDATE tblCustomers " _
& "SET CustomerLimit = 200 " _
& "WHERE CustomerID = 1"
''Error occurs here
cn.Execute s, RecordsAffected
s = "UPDATE tblCustomers " _
& "SET CustomerLimit = 90 " _
& "WHERE CustomerID = 1"
cn.Execute s, RecordsAffected
Debug.Print RecordsAffected
''Clean up
''You cannot do this through the database window,
''because of the constraint.
s = "ALTER TABLE tblCustomers DROP CONSTRAINT LimitRule "
cn.Execute s, RecordsAffected
Debug.Print RecordsAffected
s = "DROP TABLE tblCustomers "
cn.Execute s, RecordsAffected
Debug.Print RecordsAffected
s = "DROP TABLE tblCreditLimit "
cn.Execute s, RecordsAffected
Debug.Print RecordsAffected

There is Validation rule on a column.
You can use VB for Access. no SQL*Plus here...
You can always use SQL Express as a data source - with all the benefits of real sql server and use access only as a front.

To do this in Access, you need to first open the interface into ANSI-92 Query Mode. I've tested your SQL DDL code: it works fine and creates a column of type FLOAT (Double).
Is is not possible to do this using DAO but you can use ADO. Long story short: CHECK constraints were introduced into the engine in the Jet 4.0 era when the Access Team were favouring ADO. With effect from Access2007, the Access Team are back to favouring DAO but have yet to plug the Jet 4.0 'holes' in DAO. So for the majority of Jet 4.0 -only functionality (compressible data types, fixed-length text data types, fast foreign keys, etc) you need to use ADO.

You can’t use standard ANSI in the query builder UNLESS you set the database as sql ansi compatible. If you do change this setting, then you CAN can use the sql in the query builder as you have. I would not recommend changing this setting for existing databases however.
If you do, you could type in:
CREATE TABLE z1
(id int IDENTITY , FirstName CHAR, LastName CHAR, SSN INTEGER ,
check (id < 20),
constraint Mypk primary key (id) )
In you don’t need to save the sql in the query builder, and just want to type in the sql, then simply whack ctrl-g to get the access command line prompt, and you can then type in:
currentproject.Connection.Execute "CREATE TABLE
z1(id int IDENTITY , FirstName CHAR, LastName CHAR, SSN INTEGER ,
check (id < 20),
constraint Mypk primary key (id) )"
The above would be typed on one line. So, you can use the command line prompt if you want..

Related

Column names in each table must be unique. Column name 'MntNeto' in table 'CONSUMO.DBO.ARCHIVOBOL082017' is specified more than once

I need to create column: 'MntNeto' with a default value of '0', 'Not Null'
only if it does not exist in the table CONSUMO.DBO.ARCHIVOBOL082017
In Sql Server Query Analizer this string works fine, every time:
if not exists (select * from syscolumns where id=object_id('CONSUMO.DBO.ARCHIVOBOL082017') and name='MntNeto') alter table CONSUMO.DBO.ARCHIVOBOL082017 add MntNeto money default 0 not null
request.cookies("usa_bd") value is the name of the table, in this case: CONSUMO.DBO.ARCHIVOBOL082017
<%
set conn=server.createobject("adodb.connection")
'********************************************
'CONNECTION STRING **************************
%>
<!--#include file="xxxxx.asp"-->
<%
'********************************************
'********************************************
conn.open vamos
sqlstring = " if not exists (select * from syscolumns " &_
" where id=object_id('" & trim(ucase(request.cookies("usa_bd"))) & "') and name='MntNeto') " &_
" alter table " & trim(ucase(request.cookies("usa_bd"))) & " add MntNeto money default 0 not null"
response.write sqlstring & "<br><br>"
Set RS = Conn.Execute(sqlstring)
conn.close
set conn = nothing
%>
From asp it will create the column only if it does not exist.
If it does i got this error:
Column names in each table must be unique. Column name 'MntNeto' in table 'CONSUMO.DBO.ARCHIVOBOL082017' is specified more than once.
From Sql Query analyzer it works everytime with no problems, though.
The only way I know this could be happening is if your connection in your dot net app is NOT pointing to the CONSUMO database as its initial catalog. Therefore it's consulting the syscolumns table in the wrong database.
You will get the same error in SSMS if you change the connection of your query window to a different database. At least, I do.

line breaks in SQL query string from VBA

I am building a command string in VBA to be handed over to Microsoft SQL Server Management Studio which looks something like this:
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
GO
CREATE TABLE #temp
However, the command string in VBA does not include line breaks required for the GO statment which causes the execution to fail. Any ideas?
When you are building your command string, use vbCrLf to create a new line.
Example:
Dim strMyCommand As String
strMyCommand = "IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp" & vbCrLf & _
"GO" & vbCrLf & _
"CREATE TABLE #temp"
Debug.Print strMyCommand
you cannot use GO in an sql string, even if separated by carriage returns and line feeds... this is a batch separator only known to SQLCMD and SQL Server Management Studio.
For the above query you have to issue two calls to your database connection.
For instance, this works (on a local SQL Server instance) :
Sub test()
Dim oConn As ADODB.Connection
Set oConn = New Connection
oConn.ConnectionString = "Provider=SQLNCLI11;Server=(local);Integrated Security=SSPI;"
oConn.Open
oConn.Execute "IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp"
oConn.Execute "Create table #temp(somecolumn int)"
oConn.Close
End Sub
We can separate the SQL queries with a semicolon. The following should work without any issues and you only need to make one call to your database connection.
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp;CREATE TABLE #temp(ID INT);
This works on a local SQL Server instance:
Sub MyTest()
Dim con As ADODB.Connection
Set con = New Connection
con.ConnectionString = "Provider=SQLNCLI11;Server=(local);Integrated Security=SSPI;"
con.Open
con.Execute "IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp;Create table #temp(somecolumn int);"
con.Close
End Sub

Adding records to the table programatically

i am trying to append some records from a certain table to a new table ,
when i try it i am unable to append to the values
to the new table i.e "Table1" in this case what might be the reason for the data not getting appended to the table?
From what I can tell from your code you are just appending records from one table in your database into another table in the same database. You don't need to use a Recordset object to accomplish this; an INSERT INTO query will accomplish what you want.
Dim strSQL as String
Dim db as DAO.Database
Set db = CurrentDb
strSQL = "INSERT INTO Table1 ( UPI, COMPANY ) " & _
"SELECT INPUT_TBL.ID, INPUT_TBL.COMPANY FROM INPUT_TBL"
db.Execute strSQL, dbFailOnError
Set db = Nothing
Note that I used CurrentDb for the db object, under the assumption that the current database is the same one at C:\Users\test.accdb. If that's not the case, then you will need to do one of two things:
If you can add both of these tables as linked tables to the database you are running this code in, you can just use the same code as above. Instructions on how to add tables from an external database to your current database are available here: http://office.microsoft.com/en-us/access-help/import-or-link-to-data-in-another-access-database-HA001227658.aspx#BM3 and many other places on the internet.
If you can't add linked tables to your database for some reason, you can add IN clauses to the previous SQL string, which would become:
Dim strSQL as String
Dim db as DAO.Database
Dim dbname as String
Set db = CurrentDb
dbname = "C:\Users\test.accdb"
strSQL = "INSERT INTO Table1 ( UPI, COMPANY ) IN """ & dbname & """ " & _
"SELECT INPUT_TBL.ID, INPUT_TBL.COMPANY FROM INPUT_TBL IN """ & dbname & """"
db.Execute strSQL, dbFailOnError
Set db = Nothing
This code would allow you select the data from Table1 in the external database and add it to INPUT_TBL in the same external database.

Change data type of column in multiple tables in Access with VBA

I am fairly new to using VBA in MS Access and I am having trouble embedding SQL statements into VBA code. I have a database with almost 200 tables, and I would like to change the data type of one column (named lake) in each table to a "text" data type. I wrote the following code, but keep getting a syntax error for the ALTER TABLE statement.
Public Sub changeDataType()
Dim db As DAO.Database
Dim table As DAO.TableDef
Set db = CurrentDb
For Each table In db.TableDefs
DoCmd.RunSQL "ALTER TABLE" & table.Name & "ALTER COLUMN [lake] TEXT(100);"
Next
Set db = Nothing
End Sub
Can anyone tell me why I'm getting the syntax error?
Thanks,
Paul
this statement will not be correct:
DoCmd.RunSQL "ALTER TABLE" & table.Name & "ALTER COLUMN [lake] TEXT(100);"
if, for instance "table.Name" = "myTable", the resulting statement will look like this:
DoCmd.RunSQL "ALTER TABLEmyTableALTER COLUMN [lake] TEXT(100);"
try adding a space to separate the name, like this:
DoCmd.RunSQL "ALTER TABLE [" & table.Name & "] ALTER COLUMN [lake] TEXT(100);"

CREATE TABLE, CHECK possible text values

I'm using MS Access 2010 and I'm trying to create tables using SQL. I would like to put in some check constraints but I'm having some troubles:
CREATE TABLE Test (
tester Text CHECK (tester IN ('ABC', 'BCD', 'CDE'))
);
I'm getting a syntax error,
Any suggestions?
Thank you!
EDIT: Sorry if I wasn't clear. What I would like actually is to CHECK that tester is either "ABC", "BCD" or "CDE" those are the only values he can have.
EDIT2: I tried something else:
CREATE TABLE Test (
tester Text NOT NULL,
CONSTRAINT m_pk PRIMARY KEY(tester),
CONSTRAINT check_tester CHECK (DATALENGTH(tester) > 2)
);
and I also get a syntax error. Is there something I'm really not understanding with checking Text values? I can't possibly see where either of these is wrong.
Beginning with Jet 4, CHECK contraints are supported for Access DDL executed from ADO, but not from DAO.
You can execute a single DDL statement which creates the table Test with your constraint. You don't need to execute one statement to create the table and then another to add the constraint.
CREATE TABLE Test
(
tester TEXT(255),
CONSTRAINT ABC_or_BCD_or_CDE CHECK
(
tester IN ('ABC', 'BCD', 'CDE')
)
);
I formatted it that way to make it easier to examine the pieces. You could use this VBA to execute the statement:
strSql = "CREATE TABLE Test ( tester Text(255)," & vbCrLf & _
"CONSTRAINT ABC_or_BCD_or_CDE" & vbCrLf & _
"CHECK ( tester IN ('ABC', 'BCD', 'CDE')));"
Debug.Print strSql
CurrentProject.Connection.Execute strSql
Notes:
CurrentProject.Connection is an ADO object, so its .Execute method succeeds. The same statement with CurrentDb.Execute (a DAO method) would fail.
With ADO, declaring a field as TEXT without including a length (tester TEXT instead of tester TEXT(255)) will give you a memo field.
You will need to run against a connection:
ssql = "CREATE TABLE Test (tester Text)"
CurrentProject.Connection.Execute ssql
ssql = "ALTER TABLE test ADD CONSTRAINT " _
& "myrule CHECK (tester IN ('ABC', 'BCD', 'CDE'))"
CurrentProject.Connection.Execute ssql
Or
sSQL = "CREATE TABLE Test (tester Text, " _
& "CONSTRAINT myrule CHECK (tester IN ('ABC', 'BCD', 'CDE')))"
Note that the name, myrule in this case, must not already exists, even for a different table.
Some notes: Is it possible to create a check constraint in access and/or DAO?
My bad,
It appears MS Access does not allow CHECK Constraints except for primary and foreign keys. My teacher taught her course with Oracle until last year and apparently did not see that this could not be done in MS Access.