我有一个包允许我从存储过程REF_CURSOR
变量的输出创建一个表。我将它与DevPress XPO Source一起使用,以便将大量结果返回给我的客户端应用程序。
我曾经创建一个实体表,添加一个键,索引它并将新表名返回给提供给XPO源的客户端,它正在工作。但是,使用实体表不是最佳解决方案,所以我开始使用GTT。
如果我在TOAD中执行包,我的数据会被保留,但是如果我从C#执行命令,那么执行后我的表中就没有数据了。连接尚未关闭,所以我不能100%确定为什么我的数据不存在。
我可以设置连接上下文中的某些内容以确保所有执行都发生在同一个会话中吗?有一个execute immediate
语句来填充表,我认为当我执行包时,TOAD可能会使用相同的上下文。
以下是我的一些代码:
FUNCTION Build_Table_from_Cursor(REF_CURSOR SYS_REFCURSOR, ID NUMBER, AddKeyField CHAR) RETURN VARCHAR2 AS
QueryCursor SYS_REFCURSOR;
CursorNumber NUMBER;
p_tablename varchar2(30);
pk_name varchar2(30);
BEGIN
QueryCursor := REF_CURSOR;
CursorNumber := DBMS_SQL.TO_CURSOR_NUMBER(QueryCursor);
p_tablename := 'TEMPTABLE';
UTIL.create_table_from_cursor(CursorNumber, p_tablename); --This creates the GTT with all the columns
Execute immediate 'TRUNCATE TABLE ' || p_tablename; --To Add the key this must be done otherwise there is an error
pk_name := substr(p_tablename, INSTR(p_tablename, '.') + 1);
IF(AddKeyField = 'Y') THEN --Sometimes the Key field already exists
EXECUTE IMMEDIATE 'ALTER TABLE ' || p_tablename || ' ADD (KEY_FIELD_ NUMBER)';
END IF;
EXECUTE IMMEDIATE 'CREATE UNIQUE INDEX ' || p_tablename || 'KEY_INDEX ON ' || p_tablename || ' (KEY_FIELD_)';
EXECUTE IMMEDIATE 'ALTER TABLE ' || p_tablename || ' ADD CONSTRAINT pk_' || pk_name || ' PRIMARY KEY( KEY_FIELD_ )';
QueryCursor := DBMS_SQL.TO_REFCURSOR(CursorNumber);
PDS.UTIL.POPULATE_TABLE_FROM_CURSOR(QueryCursor, p_tablename, 1000); --This populates the table
EXECUTE IMMEDIATE 'UPDATE ' || p_tablename || ' SET KEY_FIELD_ = ROWNUM';
COMMIT;
return p_tablename;
END Build_Table_from_Cursor;
当我在TOAD中执行时,这非常有效。
当我运行时
using (var conn = factory.CreateConnection(Dal.ConnectionStrings[connectionString].ConnectionString))
{
conn.Open();
using (var cmd = factory.CreateCommand(CommandType.StoredProcedure, storedProcedureName))
{
var storedProcedureRow = commandExecuteDataSet.StoredProcedure[0];
foreach (var parametersRow in commandExecuteDataSet.Parameters)
{
cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter(parametersRow.Name, parametersRow.Value ?? "", GetDBTypeFromString(parametersRow.OracleDbType)));
}
cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter(storedProcedureRow.RefCursorName, DbType.Object, ParameterDirection.Output, true));
cmd.ExecuteNonQuery();
var refCursor = cmd.Parameters[storedProcedureRow.RefCursorName].Value;
cmd.Parameters.Clear();
cmd.CommandText = "SERVERMODE_UTIL.Build_Table_from_Cursor";
cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter("REF_CURSOR", refCursor));
cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter("ID", biID));
cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter("AddKeyField", "Y"));
cmd.Parameters.Add(CustomDbProviderFactory.CreateParameter("p_tablename", DbType.String, ParameterDirection.ReturnValue));
cmd.ExecuteNonQuery();
var tempTableName = cmd.Parameters["p_tablename"].Value.ToString();
tempTableName = tempTableName.Substring(tempTableName.IndexOf(".") + 1);
}
}
作为更大包的一部分,这是为创建GTT而执行的代码
l_statement := 'CREATE GLOBAL TEMPORARY TABLE ' || l_tablename || ' (' || CHR(13) || CHR(10) || l_statement || CHR(13) || CHR(10) || ') ON COMMIT PRESERVE ROWS';
execute immediate l_statement;