使用 NPGSQL 执行原始 SQL 时如何得到 "no rows" 错误?
How to get "no rows" error when execute raw SQL with NPGSQL?
我是 C# 的新手,所以如果这是一个显而易见的问题但我似乎找不到答案,我深表歉意。我正在编写一个客户端应用程序,它采用原始 SQL 命令并将其直接传递给数据库。我不知道它会是 select
、update
、insert
还是 delete
。如果是select
,我想把结果变成DataTable
。如果是别的,我想知道是执行成功了还是执行出错了(比如:没有行受到影响)。
我目前正在执行以下代码,然后才发现 return update
或 delete
的任何错误都不会影响任何行。我格式化了代码,但试图留下足够的空间来理解我想要做什么。由于这是我在这里的第一个问题,如果您有任何关于如何更好地将我的问题背景化的提示,请分享。
class Client
{
static void Main(string[] args)
{
Config.LoadConfig();
Db.Init();
var testQuery1 = "select * from test where 1=1";
var testQuery2 = "update test set value='value3' where name = 'name3'";
var testQuery3 = "insert into test (id, name, value, date) values (4,'name4','value4',current_timestamp)";
Db.Query(testQuery1);
Db.PrintResults();
Db.Query(testQuery2);
Db.PrintResults();
Db.Query(testQuery3);
Db.PrintResults();
}
}
/// <summary>
/// Universal database class.
/// </summary>
public static partial class Db
{
private static IUniversalDatabase _dbUniConn;
/* Database Results */
public static string ErrorCode { get; private set; }
public static string ErrorMessage { get; private set; }
public static int RowCount { get; private set; }
public static double ExecutionSeconds { get; private set; }
public static DataTable Data { get; private set; } = new DataTable();
public static void Init(string connString, Type dbType)
{
try
{
_connString = connString;
_connType = dbType;
switch (_connType)
{
case Db.Type.PostgreSQL:
_dbUniConn = new PostgresDatabase(_connString);
break;
...
}
}
}
public static void Open()
{ ... _dbUniConn.Open(); ... }
public static void Close()
{ ... _dbUniConn.Close(); ... }
public static void Query(string cmdString)
{
var start = DateTime.Now;
Open();
/* Reset Data */
Data.Reset();
RowCount = 0;
ErrorMessage = "";
ErrorCode = "";
/* Execute Query */
_dbUniConn.Query(cmdString);
/* Execution Time */
ExecutionSeconds = (DateTime.Now - start).TotalSeconds;
Debug.Write("Database: Execution Time: " + ExecutionSeconds.ToString() + " seconds", Debug.TraceLevel.Info);
/* RowCount and Error Message */
RowCount = Data.Rows.Count;
Debug.Write("Database: Returning " + RowCount.ToString() + " rows", Debug.TraceLevel.Info);
Debug.Write("Database: Error (" + ErrorCode + "): " + ErrorMessage, Debug.TraceLevel.Info);
Close();
}
public class PostgresDatabase : IUniversalDatabase
{
private NpgsqlConnection _dbConn;
public PostgresDatabase(string connString)
{ _dbConn = new NpgsqlConnection(connString); }
public void Open()
{ _dbConn.Open(); }
public void Close()
{ _dbConn.Close(); }
public void Dispose()
{ _dbConn.Dispose(); }
public void Query(string cmdString)
{
NpgsqlCommand cmd = new NpgsqlCommand(cmdString, _dbConn);
NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd);
cmd.CommandType = System.Data.CommandType.Text;
try
{
da.Fill(Data);
}
catch (Exception e)
{
MatchCollection configVar = Regex.Matches(e.Message.ToString(), @"^(?<code>.*?): (?<msg>.*?)$");
foreach (Match match in configVar)
{
ErrorCode = match.Groups["code"].Value.ToString();
ErrorMessage = match.Groups["msg"].Value.ToString();
}
}
da.Dispose();
cmd.Dispose();
}
}
}
我通过在查询以 select
:
以外的任何内容开始时将 RETURNING 1
添加到我的查询中来解决此问题
public void Query()
{
Match m = Regex.Match(QueryInput.queryString, @"^\s*(?i:select).*$");
if (!m.Success)
{
QueryInput.queryString += " RETURNING 1";
}
NpgsqlCommand cmd = new NpgsqlCommand(QueryInput.queryString, _dbConn);
NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd);
cmd.CommandType = System.Data.CommandType.Text;
try
{
da.Fill(Data);
}
catch (Exception e)
{
m = Regex.Match(e.Message.ToString(), @"^(?<code>.*?): (?<msg>.*?)$");
if (m.Success)
{
ErrorCode = m.Groups["code"].Value.ToString();
ErrorMessage = m.Groups["msg"].Value.ToString();
}
else
throw e;
}
da.Dispose();
cmd.Dispose();
}
}
我用以下方法对此进行了测试:
Db.Query("update test set value = 'value1' where name in (\nselect name from test where name = 'name1')", Db.Type.PostgreSQL);
Db.PrintResults();
Db.Query("\nSELECT * from test limit 10", Db.Type.PostgreSQL);
Db.PrintResults();
Db.Query("update test set value='new value' where name='name1'", Db.Type.PostgreSQL);
Db.PrintResults();
Db.Query("insert into test (id,name,value,date) values (3,'name3',value3,current_timestamp)", Db.Type.PostgreSQL);
Db.PrintResults();
Db.Query("delete from test where id = 3", Db.Type.PostgreSQL);
Db.PrintResults();
这返回了以下结果:
13:43:57:014 - Info - Database: Received [PostgreSQL] command (update test set value = 'value1' where name in (
select name from test where name = 'name1'))
13:43:57:015 - Debug - Database: Connection is now opened.
13:43:57:070 - Info - Database: Execution Time: 0.055539 seconds
13:43:57:071 - Info - Database: Returning 1 rows
13:43:57:071 - Info - Database: Error (0): Success.
13:43:57:071 - Debug - Database: Connection is now closed.
13:43:57:072 - Debug - Database: Result ?column?
13:43:57:072 - Debug - Database: Result 1: 1
13:43:57:072 - Info - Database: Received [PostgreSQL] command (
SELECT * from test limit 10)
13:43:57:072 - Debug - Database: Connection is now opened.
13:43:57:088 - Info - Database: Execution Time: 0.0160114 seconds
13:43:57:088 - Info - Database: Returning 2 rows
13:43:57:088 - Info - Database: Error (0): Success.
13:43:57:089 - Debug - Database: Connection is now closed.
13:43:57:089 - Debug - Database: Result id name value date
13:43:57:089 - Debug - Database: Result 1: 1 name1 value1 6/14/2017 8:37:48 PM
13:43:57:089 - Debug - Database: Result 2: 2 name2 value2 6/14/2017 8:37:48 PM
13:43:57:089 - Info - Database: Received [PostgreSQL] command (update test set value='new value' where name='name1')
13:43:57:089 - Debug - Database: Connection is now opened.
13:43:57:090 - Info - Database: Execution Time: 0.0010007 seconds
13:43:57:090 - Info - Database: Returning 1 rows
13:43:57:091 - Info - Database: Error (0): Success.
13:43:57:092 - Debug - Database: Connection is now closed.
13:43:57:093 - Debug - Database: Result ?column?
13:43:57:093 - Debug - Database: Result 1: 1
13:43:57:094 - Info - Database: Received [PostgreSQL] command (insert into test (id,name,value,date) values (3,'name3',value3,current_timestamp))
13:43:57:096 - Debug - Database: Connection is now opened.
13:43:57:186 - Info - Database: Execution Time: 0.0920653 seconds
13:43:57:187 - Info - Database: Returning 0 rows
13:43:57:191 - Info - Database: Error (42703): column "value3" does not exist
13:43:57:192 - Debug - Database: Connection is now closed.
13:43:57:199 - Debug - Database: Result
13:43:57:200 - Info - Database: Received [PostgreSQL] command (delete from test where id = 3)
13:43:57:201 - Debug - Database: Connection is now opened.
13:43:57:204 - Info - Database: Execution Time: 0.0040029 seconds
13:43:57:204 - Info - Database: Returning 0 rows
13:43:57:205 - Info - Database: Error (-1403): No rows found.
13:43:57:205 - Debug - Database: Connection is now closed.
13:43:57:206 - Debug - Database: Result ?column?
我是 C# 的新手,所以如果这是一个显而易见的问题但我似乎找不到答案,我深表歉意。我正在编写一个客户端应用程序,它采用原始 SQL 命令并将其直接传递给数据库。我不知道它会是 select
、update
、insert
还是 delete
。如果是select
,我想把结果变成DataTable
。如果是别的,我想知道是执行成功了还是执行出错了(比如:没有行受到影响)。
我目前正在执行以下代码,然后才发现 return update
或 delete
的任何错误都不会影响任何行。我格式化了代码,但试图留下足够的空间来理解我想要做什么。由于这是我在这里的第一个问题,如果您有任何关于如何更好地将我的问题背景化的提示,请分享。
class Client
{
static void Main(string[] args)
{
Config.LoadConfig();
Db.Init();
var testQuery1 = "select * from test where 1=1";
var testQuery2 = "update test set value='value3' where name = 'name3'";
var testQuery3 = "insert into test (id, name, value, date) values (4,'name4','value4',current_timestamp)";
Db.Query(testQuery1);
Db.PrintResults();
Db.Query(testQuery2);
Db.PrintResults();
Db.Query(testQuery3);
Db.PrintResults();
}
}
/// <summary>
/// Universal database class.
/// </summary>
public static partial class Db
{
private static IUniversalDatabase _dbUniConn;
/* Database Results */
public static string ErrorCode { get; private set; }
public static string ErrorMessage { get; private set; }
public static int RowCount { get; private set; }
public static double ExecutionSeconds { get; private set; }
public static DataTable Data { get; private set; } = new DataTable();
public static void Init(string connString, Type dbType)
{
try
{
_connString = connString;
_connType = dbType;
switch (_connType)
{
case Db.Type.PostgreSQL:
_dbUniConn = new PostgresDatabase(_connString);
break;
...
}
}
}
public static void Open()
{ ... _dbUniConn.Open(); ... }
public static void Close()
{ ... _dbUniConn.Close(); ... }
public static void Query(string cmdString)
{
var start = DateTime.Now;
Open();
/* Reset Data */
Data.Reset();
RowCount = 0;
ErrorMessage = "";
ErrorCode = "";
/* Execute Query */
_dbUniConn.Query(cmdString);
/* Execution Time */
ExecutionSeconds = (DateTime.Now - start).TotalSeconds;
Debug.Write("Database: Execution Time: " + ExecutionSeconds.ToString() + " seconds", Debug.TraceLevel.Info);
/* RowCount and Error Message */
RowCount = Data.Rows.Count;
Debug.Write("Database: Returning " + RowCount.ToString() + " rows", Debug.TraceLevel.Info);
Debug.Write("Database: Error (" + ErrorCode + "): " + ErrorMessage, Debug.TraceLevel.Info);
Close();
}
public class PostgresDatabase : IUniversalDatabase
{
private NpgsqlConnection _dbConn;
public PostgresDatabase(string connString)
{ _dbConn = new NpgsqlConnection(connString); }
public void Open()
{ _dbConn.Open(); }
public void Close()
{ _dbConn.Close(); }
public void Dispose()
{ _dbConn.Dispose(); }
public void Query(string cmdString)
{
NpgsqlCommand cmd = new NpgsqlCommand(cmdString, _dbConn);
NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd);
cmd.CommandType = System.Data.CommandType.Text;
try
{
da.Fill(Data);
}
catch (Exception e)
{
MatchCollection configVar = Regex.Matches(e.Message.ToString(), @"^(?<code>.*?): (?<msg>.*?)$");
foreach (Match match in configVar)
{
ErrorCode = match.Groups["code"].Value.ToString();
ErrorMessage = match.Groups["msg"].Value.ToString();
}
}
da.Dispose();
cmd.Dispose();
}
}
}
我通过在查询以 select
:
RETURNING 1
添加到我的查询中来解决此问题
public void Query()
{
Match m = Regex.Match(QueryInput.queryString, @"^\s*(?i:select).*$");
if (!m.Success)
{
QueryInput.queryString += " RETURNING 1";
}
NpgsqlCommand cmd = new NpgsqlCommand(QueryInput.queryString, _dbConn);
NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd);
cmd.CommandType = System.Data.CommandType.Text;
try
{
da.Fill(Data);
}
catch (Exception e)
{
m = Regex.Match(e.Message.ToString(), @"^(?<code>.*?): (?<msg>.*?)$");
if (m.Success)
{
ErrorCode = m.Groups["code"].Value.ToString();
ErrorMessage = m.Groups["msg"].Value.ToString();
}
else
throw e;
}
da.Dispose();
cmd.Dispose();
}
}
我用以下方法对此进行了测试:
Db.Query("update test set value = 'value1' where name in (\nselect name from test where name = 'name1')", Db.Type.PostgreSQL);
Db.PrintResults();
Db.Query("\nSELECT * from test limit 10", Db.Type.PostgreSQL);
Db.PrintResults();
Db.Query("update test set value='new value' where name='name1'", Db.Type.PostgreSQL);
Db.PrintResults();
Db.Query("insert into test (id,name,value,date) values (3,'name3',value3,current_timestamp)", Db.Type.PostgreSQL);
Db.PrintResults();
Db.Query("delete from test where id = 3", Db.Type.PostgreSQL);
Db.PrintResults();
这返回了以下结果:
13:43:57:014 - Info - Database: Received [PostgreSQL] command (update test set value = 'value1' where name in (
select name from test where name = 'name1'))
13:43:57:015 - Debug - Database: Connection is now opened.
13:43:57:070 - Info - Database: Execution Time: 0.055539 seconds
13:43:57:071 - Info - Database: Returning 1 rows
13:43:57:071 - Info - Database: Error (0): Success.
13:43:57:071 - Debug - Database: Connection is now closed.
13:43:57:072 - Debug - Database: Result ?column?
13:43:57:072 - Debug - Database: Result 1: 1
13:43:57:072 - Info - Database: Received [PostgreSQL] command (
SELECT * from test limit 10)
13:43:57:072 - Debug - Database: Connection is now opened.
13:43:57:088 - Info - Database: Execution Time: 0.0160114 seconds
13:43:57:088 - Info - Database: Returning 2 rows
13:43:57:088 - Info - Database: Error (0): Success.
13:43:57:089 - Debug - Database: Connection is now closed.
13:43:57:089 - Debug - Database: Result id name value date
13:43:57:089 - Debug - Database: Result 1: 1 name1 value1 6/14/2017 8:37:48 PM
13:43:57:089 - Debug - Database: Result 2: 2 name2 value2 6/14/2017 8:37:48 PM
13:43:57:089 - Info - Database: Received [PostgreSQL] command (update test set value='new value' where name='name1')
13:43:57:089 - Debug - Database: Connection is now opened.
13:43:57:090 - Info - Database: Execution Time: 0.0010007 seconds
13:43:57:090 - Info - Database: Returning 1 rows
13:43:57:091 - Info - Database: Error (0): Success.
13:43:57:092 - Debug - Database: Connection is now closed.
13:43:57:093 - Debug - Database: Result ?column?
13:43:57:093 - Debug - Database: Result 1: 1
13:43:57:094 - Info - Database: Received [PostgreSQL] command (insert into test (id,name,value,date) values (3,'name3',value3,current_timestamp))
13:43:57:096 - Debug - Database: Connection is now opened.
13:43:57:186 - Info - Database: Execution Time: 0.0920653 seconds
13:43:57:187 - Info - Database: Returning 0 rows
13:43:57:191 - Info - Database: Error (42703): column "value3" does not exist
13:43:57:192 - Debug - Database: Connection is now closed.
13:43:57:199 - Debug - Database: Result
13:43:57:200 - Info - Database: Received [PostgreSQL] command (delete from test where id = 3)
13:43:57:201 - Debug - Database: Connection is now opened.
13:43:57:204 - Info - Database: Execution Time: 0.0040029 seconds
13:43:57:204 - Info - Database: Returning 0 rows
13:43:57:205 - Info - Database: Error (-1403): No rows found.
13:43:57:205 - Debug - Database: Connection is now closed.
13:43:57:206 - Debug - Database: Result ?column?