I'm trying to execute the below query through OracleDataReader in .NET but when I try to read the value of the column_expressions column, I always get an empty string.
SELECT ic.column_name,
ie.column_expression
FROM all_ind_columns ic
LEFT JOIN all_ind_expressions ie
ON ie.index_owner = ic.index_owner
AND ie.index_name = ic.index_name
AND ie.column_position = ic.column_position
WHERE ic.index_owner = 'owner_name'
AND ic.index_name = 'index_name'
I realized that the datatype of the column id is LONG but I'm not sure if that's the reason. Is there a way I can read the actual value of the column?
When I execute the same query through Oracle SQL developer, I can see the value.
To be able to read a column that is of LONG data type the InitialLONGFetchSize property of OracleCommand has to be set to a none zero(zero by default) value:
Unfortunately you did not provide your .NET code, so I'll give you a C# + ODP.NET unmanaged driver example:
Set-up:
create table t1(
col1 varchar2(11)
);
create index FBI on t1(upper(col1));
table T1 created.
index FBI created.
C# code:
string oraConnectionString = "Data source=nkpdb;User id=hr;password=password;";
OracleConnection oraConnection = new OracleConnection(oraConnectionString);
oraConnection.Open();
/* Would be better to put this in a stored procedure */
string sqlQuery = "select ic.column_name " +
" , ie.column_expression " +
" from all_ind_columns ic " +
" left join all_ind_expressions ie " +
" on ie.index_owner = ic.index_owner " +
" and ie.index_name = ic.index_name " +
" and ie.column_position = ic.column_position " +
" where ic.index_owner = :INDOwner " +
" and ic.index_name = :INDName" ;
OracleCommand oraCmd = new OracleCommand(sqlQuery, oraConnection);
OracleParameter indOwner = new OracleParameter("INDOwner",
OracleDbType.Varchar2);
OracleParameter indName = new OracleParameter("INDName",
OracleDbType.Varchar2);
indOwner.Value = "HR";
indName.Value = "FBI";
oraCmd.Parameters.Add(indOwner);
oraCmd.Parameters.Add(indName);
/* set up initial amount of data that the OracleDataReader
* fetches for LONG column */
oraCmd.InitialLONGFetchSize = 1000; /* set initial size */
OracleDataReader oraDataReader = oraCmd.ExecuteReader();
if (oraDataReader.HasRows)
{
while (oraDataReader.Read())
{
Console.WriteLine(oraDataReader.GetString(
oraDataReader.GetOrdinal("column_expression")));
}
}
Result:
By default the InitialLONGFetchSize property is set to 0. That's the reason why you are getting an empty string. So you either need to set this property to a value greater than zero or set it to -1 to fetch an entire LONG column.
Here 's another simple solution.
1 - Create this function
create or replace function Get_Text
(sINDEX_NAME in VARCHAR2, sIndex_owner in VARCHAR2, sColumn_position in VARCHAR2)
return varchar2
is
Long_to_Varchar varchar(32767);
begin
select COLUMN_EXPRESSION into Long_to_Varchar
from SYS.all_ind_expressions
where INDEX_NAME = sINDEX_NAME and Index_owner=sIndex_owner and Column_position=sColumn_position;
return long_to_varchar;
exception
when others then
return 'Error occurred';
end;
2 - Use this SQL
select ic.index_name,
ic.column_name,
GET_TEXT(Ie.INDEX_NAME,Ie.Index_owner,ie.Column_position )
from all_ind_columns ic
left join all_ind_expressions ie
on ie.index_owner = ic.index_owner
and ie.index_name = ic.index_name
and ie.column_position = ic.column_position
WHERE ic.index_owner = 'owner_name'
AND ic.index_name = 'index_name'
Related
How do INSERT INTO Firebird, with autoincrement for the primary key?
For the table fields I have:
fstPriority VARCHAR(30), fstInfo VARCHAR(100), fstDateCreated VARCHAR(30), fstDateModified VARCHAR(30), fiKeyID INTEGER PRIMARY KEY
For the INSERT INTO I have:
FbConnection fbConn = new FbConnection(stOpenConn))
fbConn.Open();
...
FbTransaction fbTransaction = fbConn.BeginTransaction();
FbCommand fbCmd = new FbCommand("INSERT INTO " + stTableName + "(" + stFieldNames + ") VALUES ( #p0, #p1, #p2, #p3, #p4 ) RETURNING fiKeyID ", fbConn, fbTransaction);
but am uncertain what should be used for the
fbCmd.Parameters.AddWithValue
fbCmd.Parameters.AddWithValue("#p0", "1st value");
fbCmd.Parameters.AddWithValue("#p1", "2nd value");
fbCmd.Parameters.AddWithValue("#p2", "3rd value");
fbCmd.Parameters.AddWithValue("#p3", "4th value");
Then what? For fiKeyID, do I add
fbCmd.Parameters.AddWithValue("#p4", "");
Also, I see at http://www.firebirdfaq.org/faq29/ creating an autoincrement column, but am uncertain how to do this in C# ... Firebird ADO.NET ... FirebirdClient.5.8.0 ... Visual Studio 2013.
CREATE GENERATOR ...;
SET GENERATOR ...;
set term !! ;
CREATE TRIGGER ...
are not recognized by the Visual Studio compiler.
An important thing is that SET TERM is not part of the Firebird statement syntax, instead it is a client-side feature to set the statement terminator in query tools like ISQL. This terminator is necessary to know when a statement is complete and can be sent to the server. By default these tools do that on a semi-colon (;), but that doesn't work with PSQL (stored procedures, triggers), because PSQL code uses the semi-colon as well. To address this, these tools have SET TERM to switch this terminator.
Using the Firebird ADO.net provider however, you need to execute statements one at a time, so a statement terminator is irrelevant.
To be able to generate a primary key you can use the following solutions:
Firebird 3 has an identity type column, so you don't need to create a sequence and trigger yourself:
create table withgeneratedid(
id integer generated by default as identity primary key,
column2 varchar(100)
)
For Firebird 2.5 and earlier you will need to create a sequence and trigger:
create table withgeneratedid(
id integer primary key,
column2 varchar(100)
);
create sequence seq_withgeneratedid;
set term #;
create trigger withgeneratedid_bi before insert on withgeneratedid
as
begin
if (new.id is null) then new.id = next value for seq_withgeneratedid;
end#
set term ;#
When you insert values into a table and want to have a generated key, you should not include the id column in the column-list. Including the id column allows you to override the key value, but that might lead to future inserts generating a duplicate key!. If you do include the id column, then no key will be generated in the Firebird 3 example, in the Firebird 2.5 example a key will be generated if the value of the column is null, otherwise it will take the provided value.
In ADO.net you'd normally need to execute the statements individually (and not use set term). Alternatively, you could use FbScript to parse a DDL script and execute the parse statements. Note that FbScript does support (and even requires) set term.
To execute this with the Firebird ADO.net provider, you can do something like the example below. I have included three alternatives for creating the table Firebird3, Firebird2_5, and FbScriptFB2_5 (which is the same as Firebird2_5 but uses FbScript). It also show how to retrieve the generated key:
namespace FbGeneratedKeys
{
class Program
{
private static SolutionType solutionType = SolutionType.FbScriptFB2_5;
static void Main(string[] args)
{
var connectionString = new FbConnectionStringBuilder
{
Database = #"D:\temp\generatedkey.fdb",
ServerType = FbServerType.Default,
UserID = "SYSDBA",
Password = "masterkey",
}.ToString();
FbConnection.CreateDatabase(connectionString, pageSize: 8192, overwrite : true);
using (FbConnection connection = new FbConnection(connectionString))
using (FbCommand cmd = new FbCommand())
{
connection.Open();
cmd.Connection = connection;
switch (solutionType) {
case SolutionType.Firebird3:
Firebird3Example(cmd);
break;
case SolutionType.Firebird2_5:
Firebird2_5Example(cmd);
break;
case SolutionType.FbScriptFB2_5:
FbScriptFB2_5Example(cmd);
break;
}
cmd.CommandText = #"insert into withgeneratedid(column2) values (#column2) returning id";
cmd.Parameters.AddWithValue("#column2", "some value");
cmd.Parameters.Add(new FbParameter() { Direction = System.Data.ParameterDirection.Output });
cmd.ExecuteNonQuery();
Console.WriteLine("Id:" + cmd.Parameters[1].Value);
Console.ReadLine();
}
}
private static void Firebird3Example(FbCommand cmd)
{
// Firebird 3 identity column
cmd.CommandText = #"create table withgeneratedid(
id integer generated by default as identity primary key,
column2 varchar(100)
)";
cmd.ExecuteNonQuery();
}
private static void Firebird2_5Example(FbCommand cmd)
{
// Firebird 2.5 and earlier normal primary key with trigger to generate key
// Table
cmd.CommandText = #"create table withgeneratedid(
id integer primary key,
column2 varchar(100)
)";
cmd.ExecuteNonQuery();
// Sequence
cmd.CommandText = "create sequence seq_withgeneratedid";
cmd.ExecuteNonQuery();
// Trigger
cmd.CommandText = #"create trigger withgeneratedid_bi before insert on withgeneratedid
as
begin
if (new.id is null) then new.id = next value for seq_withgeneratedid;
end";
cmd.ExecuteNonQuery();
}
private static void FbScriptFB2_5Example(FbCommand cmd)
{
string script = #"
create table withgeneratedid(
id integer primary key,
column2 varchar(100)
);
create sequence seq_withgeneratedid;
set term #;
create trigger withgeneratedid_bi before insert on withgeneratedid
as
begin
if (new.id is null) then new.id = next value for seq_withgeneratedid;
end#
set term ;#
";
FbScript fbScript = new FbScript(script);
fbScript.Parse();
FbBatchExecution exec = new FbBatchExecution(cmd.Connection);
exec.AppendSqlStatements(fbScript);
exec.Execute();
}
}
enum SolutionType
{
Firebird3,
Firebird2_5,
FbScriptFB2_5
}
}
Definitions:
public const string stMAIN_TABLE_NAME = " OrgTable ";
public const string stDELETED_TABLE_NAME = " BackupTable ";
public const string stFIELD_DEFINITIONS = " fstPriority VARCHAR(30)" +
", fstInfo VARCHAR(100)" +
", fstDateCreated VARCHAR(30)" +
", fstDateModified VARCHAR(30)" +
", fiKeyID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY ";
public const string stFIELD_NAMES = " fstPriority" +
", fstInfo" +
", fstDateCreated" +
", fstDateModified" +
", fiKeyID ";
public const string stFIELD_NAMES_NO_KEY_ID = " fstPriority" +
", fstInfo" +
", fstDateCreated" +
", fstDateModified ";
Code:
//------------------------------
static private bool boCreateDatabaseTables(string stPathFilename,
string stUserID,
string stPassword,
List<string> liststTableNames,
List<string> liststFieldDefinitions)
{
bool boErrorFlag = false;
int iTablesCount = liststTableNames.Count();
string stOpenConn = new FbConnectionStringBuilder {
Database = stPathFilename,
UserID = stUserID,
Password = stPassword,
ServerType = FbServerType.Embedded,
ClientLibrary = stCLIENT_LIBRARY
}.ToString();
using (FbConnection fbConn = new FbConnection(stOpenConn)) {
try {
fbConn.Open();
FbTransaction fbTransaction = fbConn.BeginTransaction();
for (int ii = 0; ii < iTablesCount; ii++) {
string stSql = "CREATE TABLE " + liststTableNames[ii] + "( " + liststFieldDefinitions[ii] + ")";
FbCommand fbCmd = new FbCommand(stSql, fbConn, fbTransaction);
fbCmd.ExecuteNonQuery();
}
fbTransaction.Commit();
}
catch (Exception ex) {
boErrorFlag = true;
MessageBox.Show("catch ... GlobalsFirebird ... boCreateDatabaseTables ... " + ex.Message);
}
}
return boErrorFlag;
}//boCreateDatabaseTables
//------------------------------
//------------------------------
static public bool boAddRow(string stPathFilename,
string stUserID,
string stPassword,
string stTableName,
string stFieldNamesNoKeyId,
List<string> liststFieldValuesNoKeyId)
{
bool boErrorFlag = false;
string stOpenConn = new FbConnectionStringBuilder {
Database = stPathFilename,
UserID = stUserID,
Password = stPassword,
ServerType = FbServerType.Embedded,
ClientLibrary = stCLIENT_LIBRARY
}.ToString();
using(FbConnection fbConn = new FbConnection(stOpenConn)) {
fbConn.Open();
try {
string stValuesPlaceHolder = "#p0";
for (int iii = 1; iii < liststFieldValuesNoKeyId.Count; iii++)
stValuesPlaceHolder += ", #p" + (iii).ToString();
FbTransaction fbTransaction = fbConn.BeginTransaction();
string stCmd = "INSERT INTO " + stTableName + "(" + stFieldNamesNoKeyId + ") VALUES ( " + stValuesPlaceHolder + " ) RETURNING fiKeyID ";
FbCommand fbCmd = new FbCommand(stCmd, fbConn, fbTransaction);
for (int iii = 0; iii < liststFieldValuesNoKeyId.Count; iii++) {
string stPlaceHolder = "#p" + (iii).ToString();
string stValue = liststFieldValuesNoKeyId[iii];
fbCmd.Parameters.AddWithValue(stPlaceHolder, stValue);
}
fbCmd.Parameters.Add(new FbParameter() { Direction = System.Data.ParameterDirection.Output });
fbCmd.ExecuteNonQuery();
fbTransaction.Commit();
}
catch (Exception ex) {
boErrorFlag = true;
MessageBox.Show("catch ... GlobalsFirebird ... boAddRow ... " + ex.Message);
}
}
return boErrorFlag;
}//boAddRow
//------------------------------
I need to update a table called Calculated in my database, but because I have so many values that I have stored in my system as variables to add/update in the table, I created a separate table in the database called Database Relationships.
This Database Relationships table has a column called Calculated Value which holds all the field names of the Calculated table. The other column, System Field holds all the names of variables that I have created and given values to, which are of all string type and that relate to the corresponding Calculated Value
So by using a FOREACH loop
OleDbDataAdapter relationshipAdapter = new OleDbDataAdapter(relationshipCmd);
DataTable relationshipTable = new DataTable();
relationshipAdapter.Fill(relationshipTable);
string update = "Update [Calculated] SET ";
int i = 0;
int len = relationshipTable.Rows.Count;
foreach (DataRow drr in relationshipTable.Rows)
{
string calc = drr["Calculated Field"].ToString();
var sys = drr["System Field"].ToString();
if (i == len - 1)
{
update += "[" + calc + "] = " + sys + ";";
}
else
{
update += "[" + calc + "] = " + sys + ", ";
}
i++
}
update += "WHERE [NSN] = '" + NSN + "';";
OleDbCommand updateCmd = new OleDbCommand(update);
But this is not working, because after some debugging(?) I did a simple Console.WriteLine(sys) and it would print out the string in the System Field column, instead of the variable with the same name in the system.
I am currently using Microsoft Access as my database platform.
I think having "intermediate" table for temporary storing values in runtime for future saving in another table sounds little bid complicated for me.
If you want to map variables at runtime with column name in the database - use dictionary for example:
Dictionary<string, string> myValues = new Dictionary<string, string>();
Using in the application:
myValues["SomeColumn"] = "your value";
Then saving data to database will be:
var updateCmd = new OleDbCommand();
var query = new StringBuilder();
foreach(KeyValuePair<string, string> value in myValues)
{
string columnName = value.Key;
query.AppendLine($", {columnName} = ?");
var param = new OleDbParameter("#v", value.Value);
// Name of parameter not important, only order
}
if(query.Length > 0)
{
query.Remove(0, 1); // Remove first ',' character
query.Insert("Update [Calculated] SET ");
query.AppendLine("$WHERE [NSN] = '{NSN}';");
}
updateCmd.CommandText = query.ToString();
Very important: you need to use OleDbParameter for passing values to the query.
In you foreach loop, use this:
if (i == len - 1)
{
update += "[" + calc + "] = " + this.GetType().GetProperty(sys).GetValue(this, null)+ ";";
}
else
{
update += "[" + calc + "] = " + this.GetType().GetProperty(sys).GetValue(this, null)+ ", ";
}
The code above assumes that the variables are scoped in the same scope where you are generating your Sql.
In loop , you use the condition:
if (i == len - 1)
but you never change "len" or "i" value in the code.
I am using the code below in my C# batch job to handle a large amount (20k+) of updates and inserts. However, during testing I can see that if there is an issue, such as a constraint violation, I will only get the first error message back and no information on which record (or records) it is that caused the problem.
Is there an error handling method or technique that can be achieved either using .Net or T-SQL that could give us this functionality?
C#
private static string insertCommand =
"INSERT (ChannelCode, DrmTerrDesc, IndDistrnId, StateCode, ZipCode, EndDate, EffectiveDate, LastUpdateId, LastUpdateDate, ErrorCodes, Status) " +
"VALUES(Source.ChannelCode, Source.DrmTerrDesc, Source.IndDistrnId, Source.StateCode, Source.ZipCode, Source.EndDate, Source.EffectiveDate, Source.LastUpdateId, Source.LastUpdateDate, Source.ErrorCOdes, Source.Status)";
private static string updateCommand = "UPDATE SET Target.ChannelCode = Source.ChannelCode, Target.DrmTerrDesc = Source.DrmTerrDesc, Target.IndDistrnId = Source.IndDistrnId," +
"Target.StateCode = Source.StateCode, Target.ZipCode = Source.ZipCode, Target.EndDate = Source.EndDate, Target.EffectiveDate = Source.EffectiveDate," +
"Target.LastUpdateId = Source.LastUpdateId, Target.LastUpdateDate = Source.LastUpdateDate, Target.ErrorCodes = Source.ErrorCodes," +
"Target.Status = Source.Status ";
public static int Update(List<ZipCodeTerritory> updates, Dictionary<object, string> errorList)
{
int results = 0;
try
{
//Load updates into datatable
DataTable table = LoadData(updates, true);
//Script to create temp table
string tmpTable = "CREATE TABLE [dbo].[ZipCodeTerritoryTemp]( " +
"[ChannelCode] [char](1) NOT NULL, " +
"[DrmTerrDesc] [nvarchar](30) NOT NULL, " +
"[IndDistrnId] [char](3) NULL, " +
"[StateCode] [char](3) NOT NULL, " +
"[ZipCode] [char](9) NULL, " +
"[EndDate] [date] NOT NULL, " +
"[EffectiveDate] [date] NOT NULL, " +
"[LastUpdateId] [char](8) NULL, " +
"[LastUpdateDate] [date] NULL, " +
"[Id] [int] NULL, " +
"[ErrorCodes] [varchar](255) NULL, " +
"[Status] [char](1) NULL)";
using (SqlConnection connection = new SqlConnection(connString))
{
connection.Open();
//Create temp table
SqlCommand cmd = new SqlCommand(tmpTable, connection);
cmd.ExecuteNonQuery();
try
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
//Write to temp table
bulkCopy.DestinationTableName = "ZipCodeTerritoryTemp";
bulkCopy.WriteToServer(table);
//Merge changes in temp table with ZipCodeTerritory
string mergeSql = "merge ZipCodeTerritory as Target " +
"using ZipCodeTerritoryTemp as Source " +
"on " +
"Target.Id = Source.Id " +
"when matched then " +
updateCommand +
"when not matched then " +
insertCommand + ";";
cmd.CommandText = mergeSql;
results = cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
SendEmail.ErrorMail(ex.Message);
}
finally
{
//Drop temp table
SqlCommand final = new SqlCommand("DROP TABLE [dbo].[ZipCodeTerritoryTemp]", connection);
final.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
SendEmail.ErrorMail(ex.Message);
}
return results;
}
The short answer is that you can't determine this by executing the MERGE statement, you have to check for these collisions prior to executing the MERGE.
In other words (and I can't stress this one enough): always validate your inputs.
There are two points where you can do the validation: before you bulk-copy the data to the temporary table and before you merge the temporary table into the target. Depending on the nature of your data issues you might be able to do the bulk of your validation before the data hits the server.
There are three primary classes of problems I've generally encountered with MERGE statements:
Key collisions (duplicate rows in the source)
Data format errors (e.g. string representations of dates that don't translate into DATE correctly)
Constraint failures (nulls where they're not allowed, foreign key errors, etc)
The first two can generally be detected prior to pushing the data up to the server. The third depends on the nature of your constraints... but generally we can solve these before they get to the server.
Key collisions in your data can be detected by grouping the data by the keys (Id in this case). Let's assume that you have two records with the same Id value, but you want to merge in the one with the highest LastUpdateDate. One option for this is:
var cleanupdates =
from update in updates
group update by update.Id into grp
select grp.OrderByDescending(u => u.LastUpdateDate).First();
If your constraint problems are related to null values, filter out those records that have invalid nulls using a where clause. If they're related to foreign key constraints, load those keys into a list and filter on them. You can cover a lot of the validation using LINQ queries.
The important point is that you do the validation. Otherwise your MERGE will fail, and you won't know why.
For your Merge statement you are missing one little thing
merge ZipCodeTerritory as Target " +
"using (SELECT * FROM ZipCodeTerritoryTemp) as Source " + --<-- need to select data
"on " +
"Target.Id = Source.Id " +
"when matched then " +
updateCommand +
"when not matched then " +
insertCommand + ";";
But before you go ahead with this approach Read This article from Aaron Bertrand about issues with MERGE Statement.
I would suggest you to to use IF EXISTS Method something like this ...
Update
UPDATE T
SET T.Col1 = S.Col1,
T.Col2 = S.Col2,
T.Col3 = S.Col3
FROM ZipCodeTerritory T INNER JOIN ZipCodeTerritoryTemp S
ON T.id = S.id
INSERT
INSERT INTO ZipCodeTerritory(Col1, Col2, Col3, ....)
SELECT S.Col1, S.Col2, S.Col3, ....
FROM ZipCodeTerritoryTemp S LEFT JOIN ZipCodeTerritory T
ON S.ID = T.ID
WHERE T.ID IS NULL
I am trying to select last values of the columns in the datatable from the SQL Server Database.
My code is
private void bind_chart()
{
// here i am using SqlDataAdapter for the sql server select query
SqlDataAdapter adp = new SqlDataAdapter("select last() * from Test", con);
// here am taking datatable
DataTable dt = new DataTable();
try
{
// here datatale dt is fill wit the adp
adp.Fill(dt);
// this string m catching in the stringbuilder class
// in the str m writing same javascript code that is given by the google.
// my data that will come from the sql server
// below code is same like as google's javascript code
str.Append(#" <script type='text/javascript'>
google.load('visualization', '1', {packages:['gauge']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Label');
data.addColumn('number', 'Value');");
// inside the below line dt.Rows.Count explain that
// how many rows comes in dt or total rows
str.Append("data.addRows(" + dt.Rows.Count + ");");
Int32 i;
for (i = 0; i <= dt.Rows.Count - 1; i++)
{
// i need this type of output " data.setValue(0, 0, 'Memory'); so on in the first line so for this
//m using i for the 0,1& 2 and so on . and after this i am writting zero and after this student_name using datatable
str.Append("data.setValue( " + i + "," + 0 + "," + "'" + dt.Rows[i]["x"].ToString() + "');");
// i need this type of output " data.setValue(0, 1, 80);
//so on in the first line so for this
//m using i for the 0,1& 2 and so on . and after this i am writting zero and after this percentage using datatable
str.Append("data.setValue(" + i + "," + 1 + "," + dt.Rows[i]["y"].ToString() + ") ;");
// str.Append("['" + (dt.Rows[i]["student_name"].ToString()) + "'," + dt.Rows[i]["average_marks"].ToString() + "],");
}
str.Append("var chart = new google.visualization.Gauge(document.getElementById('chart_div'));");
// in the below line i am setting the height and width of the Gauge using your own requrirement
str.Append(" var options = {width: 800, height: 300, redFrom: 90, redTo: 100,");
// str.Append(" var chart = new google.visualization.BarChart(document.getElementById('chart_div'));");
str.Append("yellowFrom: 75, yellowTo: 90, minorTicks: 5};");
str.Append("chart.draw(data, options);}");
str.Append("</script>");
lt.Text = str.ToString().TrimEnd(',');
}
catch
{
}
finally
{
}
}
And want to display the last value on the gauge.
Here I am not getting the last value from the query I generated. I dont know why.
Best and recommended method.
select top 1 * from test order by ID desc
I think Last() is not a function of sql-server
But you can get the last row by using my below way's .Try this
SELECT * FROM TableName WHERE PrimaryKeyId= (SELECT MAX(PrimaryKeyId) FROM TableName )
or , try another way.
SELECT TOP 1 * FROM TableName ORDER BY PrimaryKeyId DESC
make sure set identity for your primary key .
SQL Server doesn't support LAST() syntax. Instead you can use another approach described here - http://www.w3schools.com/sql/sql_func_last.asp
I've looked at different links (like this one), but i still can't get where does this error message comes from. I keep on counting columns, comas and so on without finding where is the problem.
int exId = stride.getExerciseId();
string timestamp = stride.getTimeStamp();
int startSec = stride.getBeginningSec();
int startMsec = stride.getBeginningMSec();
int endSec = stride.getEndSec();
int endMSec = stride.getEndMSec();
float length = stride.getLength();
float duration = stride.getDuration();
float steplength = stride.getStepLength();
float stepDuration = stride.getStepDuration();
string supportingFoot = stride.getSupportingFoot();
string query = "INSERT INTO singlesupportstate (ExerciseId , TimeStamp , SingleSupportStateStartSeconds , SingleSupportStateStartMSeconds , SingleSupportStateEndSeconds , SingleSupportStateEndMSeconds , StrideLength , StrideDuration , StepLength , StepDuration , SupportingFoot)
VALUES("+ exId +",'" + timestamp +"',"+ startSec +"," + startMsec + "," + endSec + "," + endMSec + "," + length +"," + duration + "," + steplength + "," + duration + ",'" + supportingFoot + "')";
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.ExecuteNonQuery();
this.CloseConnection();
}
EDIT :
So I changed my code in order to use Parameterized query, here is the new code that works:
if (this.OpenConnection() == true)
{
MySqlCommand cmd = connection.CreateCommand() ;
cmd.CommandText = "INSERT INTO singlesupportstate (ExerciseId , TimeStamp , SingleSupportStateStartSeconds , SingleSupportStateStartMSeconds , SingleSupportStateEndSeconds , SingleSupportStateEndMSeconds , StrideLength , StrideDuration , StepLength , StepDuration , SupportingFoot) "
+" VALUES(#exId,#timestamp,#startSec,#startMsec,#endSec,#endMSec,#length,#duration,#steplength,#stepduration,#supportingFoot)";
cmd.Parameters.Add("#exId", MySqlDbType.Int32);
cmd.Parameters.Add("#timestamp",MySqlDbType.Timestamp);
cmd.Parameters.Add("#startMsec",MySqlDbType.Int32);
cmd.Parameters.Add("#startSec",MySqlDbType.Int32);
cmd.Parameters.Add("#endSec",MySqlDbType.Int32);
cmd.Parameters.Add("#endMSec",MySqlDbType.Int32);
cmd.Parameters.Add("#length", MySqlDbType.Float);
cmd.Parameters.Add("#duration",MySqlDbType.Float);
cmd.Parameters.Add("#steplength",MySqlDbType.Float);
cmd.Parameters.Add("#stepduration", MySqlDbType.Float);
cmd.Parameters.Add("#supportingfoot", MySqlDbType.Text);
cmd.Parameters["#exId"].Value = exId;
cmd.Parameters["#timestamp"].Value = timestamp;
cmd.Parameters["#startMsec"].Value = startMsec;
cmd.Parameters["#startSec"].Value = startSec;
cmd.Parameters["#endSec"].Value = endSec;
cmd.Parameters["#endMSec"].Value = endMSec;
cmd.Parameters["#length"].Value = length;
cmd.Parameters["#duration"].Value = duration;
cmd.Parameters["#steplength"].Value =steplength;
cmd.Parameters["#stepduration"].Value =stepDuration;
cmd.Parameters["#supportingfoot"].Value =supportingFoot;
cmd.CommandTimeout = 120;
cmd.ExecuteNonQuery();
this.CloseConnection();
}
This means that in one of the values in the concatenation is breaking the INSERT because it has a comma or string delimiter, thus breaking the whole query string
Look at the actual query string after concatenation, before execution
And use parameters to remove this problem anyway and mitigate SQL injection risks.
The other option is a trigger (saym for audit or history) on the singlesupportstate table that has a broken INSERT too.
What is likely happening is one of two things:
1) There are ' quotes making your query seem it has fewer values, because it eats up the commas.
2) There are numbers being formatted with a comma rather than a point, resulting in the number 123.45 showing as 123,45, thus making the query think there are two integer values: 123 and 45 resulting in too many values.
As others have said, try and use query parameters and this won't happen again. It also saves you a lot of manual escaping of strings.