SQL Create Table Syntax Error on Constraint - sql

While trying to create some tables with constraints I have stumbled on syntax errors. I am using Microsoft Access and it keeps advising me that my second Constraint is wrong. What is going on? My code looks as follows:
CREATE TABLE STORE
(
StoreName Char(25) NOT NULL,
City Char(35) NULL
Country Char(50) NULL,
Phone Char(8) NULL,
Fax Char(15) NULL,
Email Varchar(100) NULL,
Contact Char(35) NULL,
CONSTRAINT StorePK PRIMARY KEY(StoreName),
CONSTRAINT Citizen CHECK (Country IN ('Belize', 'United States', 'Mexico','China', 'Germany', 'France', 'Netherlands'))
);

I believe you have to create the table and the use ALTER TABLE to add the constraint.
ALTER TABLE STORE
CONSTRAINT Citizen CHECK (
Country IN (
'Belize', 'United States', 'Mexico','China',
'Germany', 'France', 'Netherlands'
)
);
I don't know how much the situation has changed since Access 2000 I'm pretty certain that some limitations still apply as indicated in this old documentation:
Note The check constraint statement can only be executed through the Jet OLE DB provider and ADO; it will return an error message if
used though the Access SQL View user interface.
https://msdn.microsoft.com/en-us/library/aa140015%28office.10%29.aspx#acintsql_ddlconst

Your CREATE TABLE statement is valid Access DDL when executed from ADO/OleDb. CHECK constraints are among the DDL features added with Jet 4, and which are not supported under DAO.
That also means CHECK is not supported by default for queries run from the query designer. You might be able to work around that limitation by setting the Access option "SQL Server Compatible Syntax (ANSI 92)". However that option has other side effects. If you use it, make sure to test your existing queries to see whether they all still operate as intended.
I put your statement text in a variable and executed it successfully like this:
CurrentProject.Connection.Execute strDDL
That worked because CurrentProject.Connection is an ADO object.

Related

Why schema is required while creating a table and not while querying a table - SQL server

I'm new to the MS SQL server. Our client has given us a SQL server DB and for this DB they have configured the Service Principal Authentication. So I logged into the DB using my client company account and then I tried to create a table without giving any schema name. for example
CREATE TABLE visits (
visit_id INT PRIMARY KEY IDENTITY (1, 1),
first_name VARCHAR (50) NOT NULL,
last_name VARCHAR (50) NOT NULL,
visited_at DATETIME,
phone VARCHAR(20),
store_id INT NOT NULL,
);
so when I ran this query it gave me the below error
Msg 2760, Level 16, State 1, Line 1
The specified schema name "aashay.amballi#<company>.com" either does not exist or you do not have permission to use it.
so now when I created the table with DBO schema it created the table.
CREATE TABLE dbo.visits (
visit_id INT PRIMARY KEY IDENTITY (1, 1),
first_name VARCHAR (50) NOT NULL,
last_name VARCHAR (50) NOT NULL,
visited_at DATETIME,
phone VARCHAR(20),
store_id INT NOT NULL,
);
So now when I tried to query this visits table without any schema (i.e. DBO) select * from visits it actually gave me the result.
Also when I ran the select SCHEMA_NAME() to check what is the default schema, it returned null. So is there a possibility that when there is no default schema that is set for a user and while creating a table without a schema name it will give that error? if that is the case then while querying without any schema how it's picking the dbo schema by default?
So I'm a bit confused about how this is working. Can anyone please explain this?
This question is regarding the question that I asked a couple of days back when I'm trying to integrate MSSQL with service principal authentication with the Django Framework - Django MigrationSchemaMissing exception on Azure SQL using service principal auth
From the CREATE TABLE description:
If type_schema_name isn't specified, the SQL Server Database Engine
references type_name in the following order:
The SQL Server system data type.
The default schema of the current user in the current database.
The dbo schema in the current database.
And what is your default schema? It depends on options of CREATE USER statement used when creating your user's account:
WITH DEFAULT_SCHEMA = schema_name Specifies the first schema that will
be searched by the server when it resolves the names of objects for
this database user.
You can skip the schema in queries, but it is a best practise to always use schemas.

Table <name> already exits Error (3010)

I am new to SQL and I am trying to run a CREATE TABLE query in Ms Access 2016 but I get an error saying that "mytablename" already exits which can't be true because I also ran a DROP TABLE "mytablename" query and I got an error saying "mytablename" does not exist. Please help. Point me in the right direction at least. Here is the CREATE TABLE query.
CREATE TABLE Team(
Team_ID AUTOINCREMENT UNIQUE NOT NULL,
Name VARCHAR(40) NOT NULL,
Origin VARCHAR(40) NOT NULL,
NetWorth CURRENCY NOT NULL,
PRIMARY KEY(Team_ID)
);
See check by VBA and check by SQL for check existence of your database.
If table exists you can recreate (drop and create again) table. Alternative way is to create table if table is not exist and do nothing if table exists.

Create Table Syntax Error - MS Access, SQL view

I keep getting CREATE TABLE Syntax Error, but I don't see the error! What is causing the error?
My SQL:
CREATE TABLE my_employee
(
employee_id INTEGER PRIMARY KEY NOT NULL,
first_name VARCHAR(25) NOT NULL,
last_name VARCHAR(30) NOT NULL,
address VARCHAR(10) NOT NULL,
birthdate DATE,
salary NUMERIC(8,2) DEFAULT 15000,
marital_status CHAR(1)
);
Since your DDL statement includes DEFAULT, you must execute it with ADO. I loaded your statement into a string variable and executed it from Access 2007 like this:
CurrentProject.Connection.Execute strSql
The salary field is decimal with precision 8, scale 2, and default 15000.
DEFAULT is one of the Access SQL features added with Jet 4.0. Those features are not available for a statement executed from DAO. If you are using Access' query designer to create and execute the statement, you're using DAO. Same if you were using CurrentDb.Execute. But CurrentProject.Connection is an ADO object, so it can .Execute Jet 4.0 features.
Note NOT NULL is not necessary after PRIMARY KEY since PRIMARY KEY implies NOT NULL. However PRIMARY KEY NOT NULL does not trigger an error. The statement works as you originally wrote it as long as you execute it from ADO.
Well I was having the same problem with Ms Access 2007, but I solved it later on.
It is because actually some features are disabled by default for security reasons over there.
When it shows you syntax error, you can see the message at menu bar somewhere or at the bottom: Some Features Are Disabled For Security Reasons....
Click on the message then proceed to enable further features.
As HansUp said: "default" in DDL doesn't work here. As an alternative you can create the table without the default first and add the default via the TableDef afterwards:
CurrentDb().Execute "create table my_employee ..."
CurrentDb().TableDefs("my_employee").Fields("salary").DefaultValue = 15000
Your problem is in your PRIMARY KEY declaration
CREATE TABLE my_employee
(
employee_id INTEGER NOT NULL,
first_name VARCHAR(25) NOT NULL,
last_name VARCHAR(30) NOT NULL,
address VARCHAR(10) NOT NULL,
birthdate DATE,
salary NUMERIC(8,2) DEFAULT 15000,
marital_status CHAR(1),
PRIMARY KEY (employee_id)
);

Passing information from views to base tables in Oracle (SQL)

I have a slight problem!
I have an original base table "StaffAddressDetails":
CREATE TABLE StaffAddressDetails
(ContactID INTEGER NOT NULL,
Postcode VARCHAR (10) NOT NULL,
HouseNameOrNumber VARCHAR (50) NOT NULL,
Street VARCHAR (50) NOT NULL,
Street2 VARCHAR (50) DEFAULT '...',
Town VARCHAR (50) NOT NULL,
County VARCHAR (50) NOT NULL,
Country VARCHAR (50) NOT NULL,
StaffID INTEGER NOT NULL,
CONSTRAINT StaffAddressDetails_PK PRIMARY KEY (ContactID, Postcode),
CONSTRAINT StaADContactIDSCD FOREIGN KEY (ContactID)
REFERENCES StaffContactDetails (ContactID));
I want the members of staff to be able to see only their own details, so I have a created a view "HDPBHTTSKStaffAddDetsForSelf" and granted that view to a role "Teacher":
CREATE VIEW HDPBHTTSKStaffAddDetsForSelf AS
SELECT * FROM StaffAddressDetails
WHERE StaffID IN
(SELECT USER
FROM DUAL);
...and...
GRANT SELECT, INSERT, UPDATE ON HDPBHTTSKStaffAddDetsForSelf TO Teacher;
That all works fine - the problem comes when inserting a new row (when logged in on a teacher's account) should, say, the teacher acquire a new address and wish to add it to the school system.
The inserted row appears when queried from that teacher's account, but does not pass down to the original base table, meaning no-one except the teacher can see it, not even admin.
Is there a quick fix??
Many thanks in advance,
Zulu
You should use the WITH CHECK OPTION when creating your view, so that Teacher role members cannot insert or update data with different StaffID than their own, i.e.
create view ... as select ... from ... where ... WITH CHECK OPTION;
Further, agreeing with #danihp, only reason I see why data seem not being passed down to the table for the admin to see, is that inserting transaction is not being committed.
According to my "Pro Oracle Database 11g Administration" book:
If you don't want a user to be able to perform INSERT, UPDATE, or
DELETE operations on a view, then don't grant those object privileges
on the underlying table(s) to that user.
Of course, you want to allow DML operations to the underlying table. To me, that says you also need to make sure that the "Teacher" has appropriate permissions on the StaffAddressDetails table, as well.
GRANT SELECT, INSERT, UPDATE ON StaffAddressDetails TO Teacher;
And to echo Carl's answer, it's a good idea to create this type of view using WITH CHECK OPTION.

SQL Server triggers and sqlalchemy interference problem. Help needed

I need to have a kind of 'versioning' for some critical tables, and tried to implement it in a rather simple way:
CREATE TABLE [dbo].[Address] (
[id] bigint IDENTITY(1, 1) NOT NULL,
[post_code] bigint NULL,
...
)
CREATE TABLE [dbo].[Address_History] (
[id] bigint NOT NULL,
[id_revision] bigint NOT NULL,
[post_code] bigint NULL,
...
CONSTRAINT [PK_Address_History] PRIMARY KEY CLUSTERED ([id], [id_revision]),
CONSTRAINT [FK_Address_History_Address]...
CONSTRAINT [FK_Address_History_Revision]...
)
CREATE TABLE [dbo].[Revision] (
[id] bigint IDENTITY(1, 1) NOT NULL,
[id_revision_operation] bigint NULL,
[id_document_info] bigint NULL,
[description] varchar(255) COLLATE Cyrillic_General_CI_AS NULL,
[date_revision] datetime NULL,
...
)
and a bunch of triggers on insert/update/delete for each table, that is intended to store it's changes.
My application is based on PyQt + sqlalchemy, and when I try to insert an entity, that is stored in a versioned table, sqlalchemy fires an error:
The target table 'Heritage' of the DML statement cannot have
any enabled triggers if the statement contains
an OUTPUT clause without INTO clause.
(334) (SQLExecDirectW); [42000]
[Microsoft][ODBC SQL Server Driver]
[SQL Server]Statement(s) could not be prepared. (8180)")
What should I do? I must use sqlalchemy.
If one can give an advice to me, how can I implement versioning without triggers, it'd be cool.
You should set 'implicit_returning' to 'False' to avoid "OUTPUT" usage in query generated by SQLAlchemy (and this should resolve your issue):
class Company(sqla.Model):
__bind_key__ = 'dbnamere'
__tablename__ = 'tblnamehere'
__table_args__ = {'implicit_returning': False} # http://docs.sqlalchemy.org/en/latest/dialects/mssql.html#triggers
id = sqla.Column('ncompany_id', sqla.Integer, primary_key=True)
...
I cant seem to add a comment so adding another answer.
It's not that complicated and I would suggest it's less fragile than putting 1/2 your business logic in your domain and the other half in your database trigger.
Personally I would write my own list object with a reference to the history list for the some_list_of_other_entities and in the Remove and Add methods maintain your history records.
This way your objects are automatically up to date before even saving them into your ORM.
public class ListOfOtherEntities : System.Collections.IEnumerable
{
// Add list stuff here...
public void Remove(MyEntity obj)
{
this.List.Remove(obj);
this.History.Add(new History("Added a object!");
}
public void Remove(MyEntity obj)
{
this.List.Remove(obj);
this.History.Add(new History("Removed a object!");
}
}
This way your objects are automatically up to date before even saving them into your ORM and another developer looking at the code can see what you have done quite easily.
This won't answer your question directly but in my experience using Triggers leads to endless pain so avoid them at all cost. If you manage all of the data yourself then the simple answer is populate the version history tables yourself. It also means you have all of your business logic in one place which is a bonus!