I m using the following function to create an access table:
public static void createtable(string path, string tablename, string[] columnnames)
{
try
{
string connectionstring = creadteconnectionstring(path);
OleDbConnection myConnection = new OleDbConnection(connectionstring);
myConnection.Open();
OleDbCommand myCommand = new OleDbCommand();
myCommand.Connection = myConnection;
string columnam = "[" + columnnames[0] + "] Text";
for (int i = 1; i < columnnames.Length; i++)
{
columnam = columnam + ", [" + columnnames[i] + "] Text";
}
myCommand.CommandText = "CREATE TABLE [" + tablename + "](" + columnam + ")";
myCommand.ExecuteNonQuery();
myCommand.Connection.Close();
Console.WriteLine("Access table " + tablename + " created.");
}
catch
{
Console.WriteLine("Access table " + tablename + " already exists.");
return;
}
}
However if I open the access table in MS access the data type is Memo, not Text. Other data types link specified by MS dont seem to work at all.
Any ideas are welcome? Thanks!
The Access DDL TEXT data type behaves differently depending on the context where you execute your statement.
From DAO in Access, this creates bar as a text field. But from ADO in Access, bar will be memo type.
CREATE TABLE tblFoo (bar TEXT)
Executing that statement from an OleDb connection produces the same result as with ADO in Access.
If you want bar to be an actual text field, include a field length <= 255.
CREATE TABLE tblFoo (bar TEXT(255))
Related
I have an c# program that update 2 columns, in each table in my access database file(.mdb). Columns that I'm updatnig are short string type, I am also changing their size to 255, before updating. I have 15 files, my code is working for first 7 dbs, and crash on 8-th file. I am updating each code separately, and it crash about in the middle of database
System.Data.OleDb.OleDbException: 'Record is too large.'
Query string that is crashing :
UPDATE CARTE SET SYMBOLE = 'AGLX19.A8E', SYMBOLE2 = 'AWLX19.A8E;#P516.#PQ;#P517.#PQ;#P518.#PQ;#P519.#PQ' WHERE CODE = '2862411';
private void UpdateSYMBOLEinDatabase(string tableName, string code)
{
if (symboleMdb[0] == "")
return;
string queryString = "UPDATE " + tableName +
" SET SYMBOLE = '" + symboleMdb[0] + "', SYMBOLE2 = '" + symboleMdb[1] + "' " +
"WHERE CODE = '" + code + "';";
if (symboleMdb[1] == "")
queryString = queryString.Replace(", SYMBOLE2 = ''", "");
using (OleDbConnection connectionInput = new OleDbConnection(connectionStringInput))
using (OleDbCommand command = new OleDbCommand(queryString, connectionInput))
{
connectionInput.Open();
command.ExecuteNonQuery();
command.Dispose();
}
}
I haved checked sql string carefully (also in online checker).
I had also search on google's and found that this error, is probably connected with too many columns in my db, actually when I am opening db file, there is about 220 columns. But when I am counting columns programmaticly it shows that there is about 878 columns(before/after changing length of short string type in columns). For others tables it shows correct count.
I found that copying table, may help. But actually I also can't do that.
private void CopyDeleteCopyDeleteQuery(string tableName)
{
string queryString = "CREATE TABLE " + tableName + "O"+
" AS (SELECT * FROM " + tableName +
" WHERE CODE='0801733');";
using (OleDbConnection connectionInput = new OleDbConnection(connectionStringInput))
using (OleDbCommand command = new OleDbCommand(queryString, connectionInput))
{
connectionInput.Open();
command.ExecuteNonQuery();
command.Dispose();
}
}
System.Data.OleDb.OleDbException: 'Syntax error in CREATE TABLE statement.'
Query string :
CREATE TABLE CARTEO AS (SELECT * FROM CARTE WHERE CODE='0801733');
The limit for fields is 2kB (excluding Memo and OLE. With ~220 columns fields, you are likely to be hitting that limit.
You should normalize the table, or convert some columns to Memo fields.
I have faced a problem to update a row in SQL Serve 2008 via C#. NET application.
During runtime, the application tries to update the database but with no success. However, there is no exception, error, NOTHING. Checking the SQL Profile, the update command was sent, but not committed.
If I run the application debugging it step-by-step (via 'F11') the row is updated successfully (!?!?!?!?!)
I have copied the SQL update command and ran it on SQL Management Studio and also worked fine.
General Information:
- The only problem is in runtime mode.
- The user used is 'sa' with all granted permission
- I have ran the SAME METHODS for other tables (the only thing that changes is the table name) and it works fine.
The method responsible for it is:
public void Save(FormaResult obj)
{
try
{
bool insert = GetById(obj.SLABID) == null;
IList<string> colResult = GetColumns(TABLE);
List<string> colList = colResult.Where(TableColumns.Contains).ToList();
if (insert)
{
string col = string.Join(",", colList.Select(i => i).ToArray());
string colParam = string.Join(", ", colList.Select(i => "#" + i).ToArray());
QueryString = "INSERT INTO " + TABLE + " (" + col + ") VALUES(" + colParam + ");";
}
else
{
string colSet = string.Join(", ", colList.Select(i => i + " = #" + i).ToArray());
QueryString = "UPDATE " + TABLE + " SET " + colSet + " WHERE SLABID = #Id1;";
}
DbCommand = Conn.CreateCommand();
DbCommand.Connection = Conn;
DbCommand.CommandText = QueryString;
ListDbParameters = new List<DbParameter>
{
this.CriarParametro<DateTime>("GT_TIME", obj.GT_TIME),
this.CriarParametro<long?>("SLABID", obj.SLABID),
this.CriarParametro<short?>("STATUS", obj.STATUS)
};
if (!insert)
{
ListDbParameters.Add(this.CriarParametro<long>("Id1", obj.SLABID));
}
foreach (DbParameter param in ListDbParameters)
{
DbCommand.Parameters.Add(param);
}
Conn.Open();
DbCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
TrkCGManagedModuleService.Logger.Error(ex.Message);
throw;
}
finally
{
Conn.Close();
}
}
I have also used this method:
public void OkEvt()
{
try
{
this.QueryString = "UPDATE " + TABLE + " SET STATUS = 1 " +
"FROM (SELECT TOP(1) * FROM " + TABLE + " WHERE STATUS=0 ORDER BY GT_TIME ASC) I " +
"WHERE " + TABLE + ".SLABID = I.SLABID AND " + TABLE + ".STATUS=0 AND " + TABLE + ".GT_TIME = I.GT_TIME;";
this.DbCommand = this.Conn.CreateCommand();
this.DbCommand.Connection = this.Conn;
this.DbCommand.CommandText = this.QueryString;
this.Conn.Open();
this.DbCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
TrkCGManagedModuleService.Logger.Error(ex.Message);
throw;
}
finally
{
this.Conn.Close();
}
}
Both methods have the same aim, update the column 'STATUS' to '1'.
I would say the same thing as Soner Gonul about the SQL injection. I understand what your trying to do, but from my experience your leaving open a security door that is easily closed. Just requires a bit more time writing your CRUD statements for each table.
Here is a code sample that I use for my update queries you might find useful. If you are going to use this method, remember to create a user that has deny reader and deny writer. Then run a command to grant them execute permissions on all stored procedures.
this.o_ConnectionString is a private variable set inside my class constructor since i put my data layer in a separate project than my web applications.
public int UpdateThisTable(int TableUID, string SomeField)
{
string StoredProcedure = "usp_SomeStoredProcedure";
SqlConnection conn = new SqlConnection(enteryourconnectionstring);
SqlCommand cmd = new SqlCommand(StoredProcedure, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#TableUID", TableUID);
cmd.Parameters.AddWithValue("#SomeField", SomeField);
conn.Open();
int rowsaffected = cmd.ExecuteNonQuery();
conn.Close();
return rowsaffected;
}
Suppose I this method from my MySQLOperations class:
public bool checkIfRowExists(string tableName, string columnToLookIn, string dataToLookFor)
{
string myConnectionString = "Server = " + server + "; Database = " + dbName + "; UID = " + user + "; Password = " + password + ";";
int isExisting = 0;
using (MySqlConnection myConnection = new MySqlConnection(myConnectionString))
{
using (MySqlCommand myCommand = new MySqlCommand("SELECT EXISTS (SELECT 1 FROM #tablename WHERE #columnname = #data);", myConnection))
{
myCommand.Parameters.AddWithValue("#tablename", tableName);
myCommand.Parameters.AddWithValue("#columnname", columnToLookIn);
myCommand.Parameters.AddWithValue("#data", dataToLookFor);
try
{
myConnection.Open();
isExisting = (int)myCommand.ExecuteScalar();
myConnection.Close();
}
catch (Exception ex)
{
myConnection.Close();
MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return (isExisting == 1);
}
}
}
And in another class, I created a MySQLOperations object.
I called on this method within an if statement: if(objSQLOperations.checkIfRowExists("tblInventory", "ItemID", txtItemID.Text)). Let us assume that txtItemID contains a valid 10-digit number. And that in my database, I have a table named tblInventory with a column ItemID.
My problem is that the statements within my catch block executes, saying there was an error with my SQL syntax. "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''tblInventory' WHERE 'ItemID' = '11111111111'' at line 1." is popped at a MessageBox when my txtItemID contains the text "1111111111".
I believe my SELECT EXISTS statement is correct.
No you can't use parameters for table or column names. You'll have to build up the SQL string dynamically by concatenation.
Like:
var sql = "SELECT EXISTS(SELECT 1 FROM " + tablename +
" WHERE " + columnNameToLookIn + " = #data);"
using (MySqlCommand myCommand = new MySqlCommand(sql, myConnection))
This of course opens you up to SQL injection if tableName and columnNameToLookIn can be user entered. However if the tableName and columnNameToLookIn are only set in code as it appears in your example then it is not a problem.
Related:
use a variable for table name in mysql sproc
Dynamic table names in stored procedure function
I am attempting to write to a Paradox database file using c# and oledb in Windows 8. I am able to drop the table, create the table and write the first line before I get the error "operation must use an updateable query".
I have gone through the following to try and work it out:
1) Running as administrator
2) Updating the permissions within the application to make sure I don't have readonly or archive properties on the file
3) Adding the running user permissions to read / write / modify directories where the db files sit
4) Changing the query multiple times in case I am doing something weird with the query
If I was unable to write or insert at all then the above steps would have made sense but the initial insert works and any additional inserts fail.
The code below shows the current way I am trying to perform the actions and I have left in the commented out sections so that you can see what else I have tried.
public void OverwriteData(string fileName, DataTable dataToWrite)
{
//split up the filename
string path = Path.GetDirectoryName(fileName);
string file = Path.GetFileName(fileName);
//create the string for creating the table
string strTempCreate = "";
//string strTempInsert = "";
foreach (DataColumn column in dataToWrite.Columns)
{
if (strTempCreate != "")
{
strTempCreate = strTempCreate + ", ";
}
strTempCreate = strTempCreate + "[" + column.ColumnName + "]" + " char(30)";
/*if (strTempInsert != "")
{
strTempInsert = strTempInsert + ", ";
}
strTempInsert = strTempInsert + column.ColumnName;*/
}
string createTableStr = "CREATE TABLE " + file + " (" + strTempCreate + ")";
string dropTableStr = "DROP TABLE " + file;
//build the sql insert command
//string insertSql = "insert into " + file + " values ";
/*foreach (DataRow row in dataToWrite.Rows)
{
insertSql = insertSql + row.Field<string>;
}*/
string connectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + #";Extended Properties=Paradox 5.x;";
//DataTable results = new DataTable();
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
OleDbCommand dbCommand = new OleDbCommand();
dbCommand.Connection = conn;
dbCommand.CommandText = dropTableStr;
try
{
dbCommand.ExecuteNonQuery();
}
catch { }
dbCommand.CommandText = createTableStr;
dbCommand.ExecuteNonQuery();
//try to do the insert
StringBuilder sb = new StringBuilder();
//make sure that the database is not readonly
FileAttributes attributes = File.GetAttributes(fileName);
if ((attributes & FileAttributes.Archive) == FileAttributes.Archive)
{
attributes = attributes & ~FileAttributes.Archive;
File.SetAttributes(fileName, attributes);
}
//then we want to try and connect to this database to put data into it
string selectSQL = "Select * from " + file;
using (var adapter = new OleDbDataAdapter(selectSQL, conn))
{
using (var builder = new OleDbCommandBuilder(adapter))
{
var destinationTable = new DataTable();
adapter.Fill(destinationTable);
destinationTable.Merge(dataToWrite,true,MissingSchemaAction.Ignore);
destinationTable.AcceptChanges();
foreach (DataRow row in destinationTable.Rows)
{
row.SetAdded();
}
builder.QuotePrefix = "[";
builder.QuoteSuffix = "]";
builder.GetInsertCommand();
adapter.Update(destinationTable);
}
}
/*foreach (DataRow row in dataToWrite.Rows)
{
sb.Clear();
sb.Append("insert into " + file + " values ('");
IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString());
sb.Append(string.Join("','", fields));
sb.Append("')");
dbCommand.CommandText = sb.ToString();
dbCommand.ExecuteNonQuery();
}*/
/*sb.Clear();
sb.Append("insert into " + file);
foreach (DataRow row in dataToWrite.Rows)
{
sb.Append(" values ('");
IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString());
sb.Append(string.Join("','", fields));
sb.Append("'),");
}
sb.Remove(sb.Length - 1, 1);
sb.Append(";");
dbCommand.CommandText = sb.ToString();
dbCommand.ExecuteNonQuery();
*/
}
}
This article solved my problem: https://msdn.microsoft.com/en-us/library/ms715421(v=vs.85).aspx
According to Microsoft: A table is not updatable by the Paradox driver under two conditions:
When a unique index is not defined on the table. This is not true for
an empty table, which can be updated with a single row even if a
unique index is not defined on the table. If a single row is inserted
in an empty table that does not have a unique index, an application
cannot create a unique index or insert additional data after the
single row has been inserted.
If the Borland Database Engine is not implemented.
One of the issues I have is that, I don't think the table has a name... its just a .dbf file
So I've been trying this:
public void SQLAlter(string dbffile, string ColumnName )
{
//dbffile is "C:\MAPS\WASHINGTON\TLG_ROADS_L.DBF"
//ColumnName is "State"
if (File.Exists(dbffile))
{
System.Data.Odbc.OdbcConnection conn = new System.Data.Odbc.OdbcConnection();
conn.ConnectionString = #"DSN=dBase Files";
conn.Open();
System.Data.Odbc.OdbcCommand comm = new System.Data.Odbc.OdbcCommand();
comm.CommandText = "ALTER TABLE " + dbffile + " ADD COLUMN " + ColumnName + " VARCHAR(1024)";
comm.ExecuteNonQuery();
}
}
The error is :
base {System.Data.Common.DbException} = {"ERROR [42S02]
[Microsoft][ODBC dBASE Driver] Cannot find table or constraint."}
I believe the table name is supposed to be the filename, and the connection string should point to the folder containing the dbf file.
var path = Path.GetDirectoryName(dbffile);
var tableName = Path.GetFileName(dbffile);
// ...
conn.ConnectionSTring = #"Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=" + path;
comm.CommandText = "ALTER TABLE " + tableName + //...
Check connectionstrings.com: http://connectionstrings.com/dbf-foxpro
This is actually the correct syntax
comm.CommandText = "ALTER TABLE " + dbffile + " ADD COLUMN " + ColumnName + " VARCHAR(1024)";
However if your filename is longer than 8 characters it will not find it. Even though I tried it will an appropriate length file name, the "Operation [is] not supported on a table that contains data."
Various Internet links seem to indicate that one has to create a new table, and copy all the fields over.
Try another Provider.
It worked for me with the Visual Foxpro Provider
conn.ConnectionString = #"Provider=VFPOLEDB.1; Data Source=Themes.dbf" + #"\;Extended Properties=dBase IV";
If the driver is not installed on your machine, you get it here :
http://www.microsoft.com/en-us/download/details.aspx?id=14839