I am using PostgreSQL database with C# and the Npgsql library.
Right now I can select the last row in my table, but I can not figure out how to assign a C# variable to it. I know that my selection works, because I have successfully edited my last entry before.
You can find my code below. Note that I have not pasted the rest of the methods as I think they are irrelevant.
public void myMethod()
{
this.OpenConn(); //opens the connection
string sql = "SELECT id FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'customers' ORDER BY id DESC, LIMIT 1";
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
{
int id = 0; //instead of '0' I want it to be equal to the ID value from the row
//something like "int id = sqlSelection.id;" -- this obviously doesn't work
this.CloseConn(); //close the current connection
}
}
You could achieve this goal by using the specific DataReader:
public void myMethod()
{
this.OpenConn(); //opens the connection
string sql = "SELECT id FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'customers' ORDER BY id DESC, LIMIT 1";
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
{
int val;
NpgsqlDataReader reader = command.ExecuteReader();
while(reader.Read()){
val = Int32.Parse(reader[0].ToString());
//do whatever you like
}
this.CloseConn(); //close the current connection
}
}
Useful notes
In some contexts ExecuteScalar is a good alternative
Npgsql documentation
Use can use following code variation too;
using (var command = new NpgsqlCommand(sql, conn))
{
int id = 0;
var reader = command.ExecuteReader();
while(reader.Read())
{
var id = Int32.Parse(reader["id"].ToString());
}
this.CloseConn();
}
You can use ExecuteScalarSync method.
public void myMethod()
{
this.OpenConn(); //opens the connection
string sql = "SELECT id FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'customers' ORDER BY id DESC, LIMIT 1";
using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
{
int id= (int)DBHelperRepository.ExecuteScalarSync(sqlString, CommandType.Text);
this.CloseConn(); //close the current connection
}
}
Related
I have a query like
Select * from tablename where id in (:ids);
I want to assign a list of integers for the above parameter :ids.
I am using the ODP.Net with C#.
The code snippet will be something like this
const String sql = Select * from tablename where id in (:ids);
using(OracleCommand cmd = new OracleCommand(sql, dbc)) {
cmd.Parameters.Add(:ids, OracleDbType.Int64, 12, Ids , ParameterDirection.Input);
using(OracleDataReader rdr = cmd.ExecuteReader()) {
}
}
But its throwing some errors...
Can anybody please help on this ?
Unfortunately, you need to bind them one by one:
vat sql = string.Format("select * from tablename where id in ({0})", string.Join(",", ids.Select((v,i)=>":id"+i)));
using(OracleCommand cmd = new OracleCommand(sql, dbc)) {
int pos = 0;
foreach (var id in Ids) {
cmd.Parameters.Add("id"+pos, OracleDbType.Int64, 12, id , ParameterDirection.Input);
pos++;
}
using(OracleDataReader rdr = cmd.ExecuteReader()) {
...
}
}
First, you construct the SQL that looks like "... where id in (id0, id1, id2, ...)", then go through the actual IDs one by one in a foreach loop, and bind them to the command.
I want to get the value to insert a table in C#,something like this:
begin
insert into bk_library(floor,section) values('foo2','bar')
returning id into :outid;
select *from bk_library where id=:outid;
end;
Unfortunately, I failed
error info: Kiss.Linq.Linq2Sql.Test.EntryPoint.TestInsertReturnId:
Oracle.DataAccess.Client.OracleException : ORA-06550: line 3, column
1: PLS-00428: an INTO clause is expected in this SELECT statement
[Test]
public void TestInsertReturnId()
{
int ret = 0;
string connstring = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=pdborcl)));User Id=system;Password=****;";
string sql = #"insert into bk_library(floor,section) values('foo','bar') returning id into :outid";
sql = getSqlString();
using (DbConnection conn = new OracleConnection(connstring))
{
conn.Open();
DbCommand command = conn.CreateCommand();
command.CommandType = CommandType.Text;
command.CommandText = sql;
OracleParameter lastId = new OracleParameter(":outid", OracleDbType.Int32);
lastId.Direction = ParameterDirection.Output;
command.Parameters.Add(lastId);
ret = command.ExecuteNonQuery();
// this code work fine ,now I want to get the entire record
LogManager.GetLogger<EntryPoint>().Info("The new id ={0}", lastId.Value.ToString());
conn.Close();
}
Assert.AreNotEqual(ret, 0);
}
ParameterDirection should be ReturnValue
lastId.Direction = ParameterDirection.ReturnValue;
From < http://arjudba.blogspot.ch/2008/07/pls-00428-into-clause-is-expected-in.html?m=1>
You need to write SELECT * INTO some_variable FROM bk_library instead of SELECT * FROM bk_library because I assume you want to store the data retrieved somehow. Therefore you need to declare a new variable some_variable (I assume of type string) and modify your SELECT statement as above. The data from the statement will then be stored in your new variable.
Hope this helps
I'm trying to get the column names of a table I have stored in SQL Server 2008 R2.
I've literally tried everything but I can't seem to find how to do this.
Right now this is my code in C#
public string[] getColumnsName()
{
List<string> listacolumnas=new List<string>();
using (SqlConnection connection = new SqlConnection(Connection))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT TOP 0 * FROM Usuarios";
connection.Open();
using (var reader = command.ExecuteReader(CommandBehavior.KeyInfo))
{
reader.Read();
var table = reader.GetSchemaTable();
foreach (DataColumn column in table.Columns)
{
listacolumnas.Add(column.ColumnName);
}
}
}
return listacolumnas.ToArray();
}
But this is returning me the following
<string>ColumnName</string>
<string>ColumnOrdinal</string>
<string>ColumnSize</string>
<string>NumericPrecision</string>
<string>NumericScale</string>
<string>IsUnique</string>
<string>IsKey</string>
<string>BaseServerName</string>
<string>BaseCatalogName</string>
<string>BaseColumnName</string>
<string>BaseSchemaName</string>
<string>BaseTableName</string>
<string>DataType</string>
<string>AllowDBNull</string>
<string>ProviderType</string>
<string>IsAliased</string>
<string>IsExpression</string>
<string>IsIdentity</string>
<string>IsAutoIncrement</string>
<string>IsRowVersion</string>
<string>IsHidden</string>
<string>IsLong</string>
<string>IsReadOnly</string>
<string>ProviderSpecificDataType</string>
<string>DataTypeName</string>
<string>XmlSchemaCollectionDatabase</string>
<string>XmlSchemaCollectionOwningSchema</string>
<string>XmlSchemaCollectionName</string>
<string>UdtAssemblyQualifiedName</string>
<string>NonVersionedProviderType</string>
<string>IsColumnSet</string>
Any ideas?
It shows the <string> tags as this is how my web service sends the data.
You can use the query below to get the column names for your table. The query below gets all the columns for a user table of a given name:
select c.name from sys.columns c
inner join sys.tables t
on t.object_id = c.object_id
and t.name = 'Usuarios' and t.type = 'U'
In your code, it will look like that:
public string[] getColumnsName()
{
List<string> listacolumnas=new List<string>();
using (SqlConnection connection = new SqlConnection(Connection))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "select c.name from sys.columns c inner join sys.tables t on t.object_id = c.object_id and t.name = 'Usuarios' and t.type = 'U'";
connection.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
listacolumnas.Add(reader.GetString(0));
}
}
}
return listacolumnas.ToArray();
}
I typically use the GetSchema method to retrieve Column specific information, this snippet will return the column names in a string List:
using (SqlConnection conn = new SqlConnection("<ConnectionString>"))
{
string[] restrictions = new string[4] { null, null, "<TableName>", null };
conn.Open();
var columnList = conn.GetSchema("Columns", restrictions).AsEnumerable().Select(s => s.Field<String>("Column_Name")).ToList();
}
SELECT COLUMN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'YourTable'
public string[] getColumnsName()
{
List<string> listacolumnas=new List<string>();
using (SqlConnection connection = new SqlConnection(Connection))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "select column_name from information_schema.columns where table_name = 'Usuarios'";
connection.Open(;
using (var reader = command.ExecuteReader(CommandBehavior.KeyInfo))
{
reader.Read();
var table = reader.GetSchemaTable();
foreach (DataColumn column in table.Columns)
{
listacolumnas.Add(column.ColumnName);
}
}
}
return listacolumnas.ToArray();
}
The original post was close to the goal, Just some small changes and you got it.
Here is my solution.
public List<string> GetColumns(string tableName)
{
List<string> colList = new List<string>();
DataTable dataTable = new DataTable();
string cmdString = String.Format("SELECT TOP 0 * FROM {0}", tableName);
if (ConnectionManager != null)
{
try
{
using (SqlDataAdapter dataContent = new SqlDataAdapter(cmdString, ConnectionManager.ConnectionToSQL))
{
dataContent.Fill(dataTable);
foreach (DataColumn col in dataTable.Columns)
{
colList.Add(col.ColumnName);
}
}
}
catch (Exception ex)
{
InternalError = ex.Message;
}
}
return colList;
}
Currently, there are two ways I could think of doing this:
In pure SQL Server SQL you can use the views defined in INFORMATION_SCHEMA.COLUMNS. There, you would need to select the row for your table, matching on the column TABLE_NAME.
Since you are using C#, it's probably easier to obtain the names from the SqlDataReader instance that is returned by ExecuteReader. The class provides a property FieldCount, for the number of columns, and a method GetName(int), taking the column number as its argument and returning the name of the column.
sp_columns - http://technet.microsoft.com/en-us/library/ms176077.aspx
There are many built in stored procedures for this type of thing.
I'm trying to check if a record in a table already exists.
How could I do that?
I already wrote the following code:
string dbName = "Data Source=searchindex.db";
SQLiteConnection con = new SQLiteConnection(dbName);
con.Open();
SQLiteCommand cmd = new SQLiteCommand(con);
// If this sql request return false
cmd.CommandText = "SELECT rowid FROM wordlist WHERE word='word'";
cmd.ExecuteNonQuery();
// then add record in table
cmd.CommandText = "INSERT INTO wordlist(word) VALUES ('word')";
To check if that record exists you could simplify your code
cmd.CommandText = "SELECT count(*) FROM wordlist WHERE word='word'";
int count = Convert.ToInt32(cmd.ExecuteScalar());
if(count == 0)
{
cmd.CommandText = "INSERT INTO wordlist(word) VALUES ('word')";
cmd.ExecuteNonQuery();
}
ExecuteScalar will return the first column on the first row returned by your query.
(The link is for SqlServer, but it is identical for SQLite, because the SQLiteCommand should implement the IDbCommand interface)
Another approach to use is the following
cmd.CommandText = "INSERT INTO wordlist (word)
SELECT ('word')
WHERE NOT EXISTS
(SELECT 1 FROM wordlist WHERE word = 'word');";
cmd.ExecuteNonQuery();
This is even better because you use a single query and not two (albeit the difference in a local db should be minimal)
insert into wordlist(word)
select 'foo'
where not exists ( select 1 from wordlist where word = 'foo')
If you are using sqlite-net-pcl you could write the following.
I have a base class for several tables and in it, I have a RowExists method.
The relevant source code looks as follows:
public abstract class BaseSQLiteAccess
{
protected SQLiteConnection _databaseConnection;
protected String TableName { get; set; }
//...
protected bool RowExists(int id)
{
bool exists = false;
try
{
exists = _databaseConnection.ExecuteScalar<bool>("SELECT EXISTS(SELECT 1 FROM " + TableName + " WHERE ID=?)", id);
}
catch (Exception ex)
{
//Log database error
exists = false;
}
return exists;
}
}
I'm trying to populate a text box with a forename and surname using the code below:
using (OleDbConnection connName = new OleDbConnection(strCon))
{
String sqlName = "SELECT forename, Surname FROM customer WHERE [customerID]=" + txtCustomerID.Text;
// Create a command to use to call the database.
OleDbCommand commandname = new OleDbCommand(sqlName, connName);
connName.Open();
// Create a reader containing the results
using (OleDbDataReader readerName = commandname.ExecuteReader())
{
readerName.Read(); // Advance to the first row.
txtName.Text = readerName[0].ToString();
}
connName.Close();
}
However I'm getting the error: OleDbException was unhandled.
"no required values for one of more required parameters"
at the ExecuteReader and I'm not sure how to go about fixing this.
EDIT: this code below is nearly the exact same bar for the information in the query but this exception is not coming up for it.
string strCon = Properties.Settings.Default.PID2dbConnectionString;
using (OleDbConnection conn = new OleDbConnection(strCon))
{
String sqlPoints = "SELECT points FROM customer WHERE [customerID]=" + txtCustomerID.Text;
conn.Open();
// Create a command to use to call the database.
OleDbCommand command = new OleDbCommand(sqlPoints, conn);
// Create a reader containing the results
using (OleDbDataReader reader = command.ExecuteReader())
{
reader.Read(); // Advance to the first row.
txtPoints.Text = reader[0].ToString(); // Read the contents of the first column
}
conn.Close();
}
The usual reason for this is a null or empty string i.e. txtCustomerID.Text has no value so the query being sent to the server is:
SELECT forename, Surname FROM customer WHERE [customerID]=
You can avoid errors like this and SQL Injection, use strongly typed parameters and avoid data truncation using parameterised queries (I have assumed customer ID is an int field)
using (OleDbConnection connName = new OleDbConnection(strCon))
{
String sqlName = "SELECT forename, Surname FROM customer WHERE customerID = #CustomerID";
// Create a command to use to call the database.
using (OleDbCommand commandname = new OleDbCommand(sqlName, connName))
{
//Check the input is valid
int customerID = 0;
if (!int.TryParse(txtCustomerID.Text, out customerID))
{
txtName.Text = "Customer ID Text box is not an integer";
return;
}
connName.Open();
// Add the parameter to the command
commandname.Parameters.Add("#CustomerID", OleDbType.Integer).Value = customerID;
// Create a reader containing the results
using (OleDbDataReader readerName = commandname.ExecuteReader())
{
readerName.Read(); // Advance to the first row.
txtName.Text = readerName[0].ToString();
}
connName.Close();
}
}
You have to encode parameters used in string queries.
String sqlName = String.Format("SELECT forname, Surname FROM customer WHERE customerID={0}",txtCustomerID.Text);
But I advice you against using SQL queries hard-coded in strings. Its easy way for SQL Injection attack. You should use parammeters instead.