Force Oracle Baisse Globale De La Table Temporaire
Dans notre projet, j'ai créer une certaine mondial de la table temporaire qui sera comme celles-ci:
CREATE GLOBAL TEMPORARY TABLE v2dtemp (
id NUMBER,
GOOD_TYPE_GROUP VARCHAR2(250 BYTE),
GOOD_CODE VARCHAR2(50 BYTE),
GOOD_TITLE VARCHAR2(250 BYTE)
)
ON COMMIT PRESERVE ROWS;
mais le problème vient quand je veux supprimer ce tableau.
Oracle ne sera pas me laisser tomber de la table, et il dit:
ORA-14452: attempt to create, alter or drop an index on temporary table already in use
- Je utiliser cette table dans une procédure, mais il peut être changé dépendants à d'autres rapports. Donc je doit toujours tomber de la table puis je doit le recréer avec mon champs nécessaires.
- Je utiliser pour des raisons d'affaires de sorte qu'il n'est pas possible pour moi d'utiliser des tableaux ou d'autres choses. Je peux juste utiliser des tables temporaires.
J'ai essayé de commettre supprimer des lignes, mais quand je l'appelle ma procédure à suivre pour utiliser les données de ce tableau il n'y a plus de lignes dans la table et ils ont été supprimés.
Toute aide sera grandement appréciée,
merci d'avance
///EDIT
public void saveJSONBatchOpenJobs(final JSONArray array, MtdReport report) {
dropAndCreateTable();
String sql = "INSERT INTO v2d_temp " +
"(ID, KARPARDAZ, GOOD_TYPE_GROUP, GOOD_CODE, GOOD_TITLE, COUNT, "
+ "FACTOR_COUNT, GHABZ_COUNT, DEAL_NO, DEAL_DATE, REQUEST_NO, REQUEST_DATE, "
+ "REQUEST_CLIENT, STATUS, TYPE, MTDREPORT_ID, GEN_SECURITY_DATA_ID) " +
"VALUES (MTD_KARPARDAZ_OPEN_JOBS_SEQ.nextval,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
getJdbcTemplate().batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
JSONArray values = array.getJSONArray(i);
if(!values.get(0).equals("null"))
ps.setString(1, values.get(0).toString());
else
ps.setNull(1, Types.VARCHAR);
if(!values.get(1).equals("null"))
ps.setString(2, values.get(1).toString());
else
ps.setNull(2, Types.VARCHAR);
if(!values.get(2).equals("null"))
ps.setString(3, values.get(2).toString());
else
ps.setNull(3, Types.VARCHAR);
if(!values.get(3).equals("null"))
ps.setString(4, values.get(3).toString());
else
ps.setNull(4, Types.VARCHAR);
if(!values.get(4).equals("null"))
ps.setBigDecimal(5, new BigDecimal(values.get(4).toString()));
else
ps.setNull(5, Types.NUMERIC);
if(!values.get(5).equals("null"))
ps.setBigDecimal(6, new BigDecimal(values.get(5).toString()));
else
ps.setNull(6, Types.NUMERIC);
if(!values.get(6).equals("null"))
ps.setBigDecimal(7, new BigDecimal(values.get(6).toString()));
else
ps.setNull(7, Types.NUMERIC);
if(!values.get(7).equals("null"))
ps.setString(8, values.get(7).toString());
else
ps.setNull(8, Types.VARCHAR);
if(!values.get(8).equals("null"))
ps.setDate(9, new Date(new Timestamp(values.getLong(8)).getDateTime()));
else
ps.setNull(9, Types.DATE);
if(!values.get(9).equals("null"))
ps.setString(10, values.get(9).toString());
else
ps.setNull(10, Types.VARCHAR);
if(!values.get(10).equals("null"))
ps.setDate(11, new Date(new Timestamp(values.getLong(8)).getDateTime()));
else
ps.setNull(11, Types.DATE);
if(!values.get(11).equals("null"))
ps.setString(12, values.get(11).toString());
else
ps.setNull(12, Types.VARCHAR);
if(!values.get(12).equals("null"))
ps.setString(13, values.get(12).toString());
else
ps.setNull(13, Types.VARCHAR);
if(!values.get(13).equals("null"))
ps.setString(14, values.get(13).toString());
else
ps.setNull(14, Types.VARCHAR);
if(!values.get(14).equals("null"))
ps.setLong(15, new Long(values.get(14).toString()));
else
ps.setNull(15, Types.NUMERIC);
if(!values.get(15).equals("null"))
ps.setLong(16, new Long(values.get(15).toString()));
else
ps.setNull(16, Types.NUMERIC);
}
@Override
public int getBatchSize() {
return array.size();
}
});
String bulkInsert = "declare "
+ "type array is table of d2v_temp%rowtype;"
+ "t1 array;"
+ "begin "
+ "select * bulk collect into t1 from d2v_temp;"
+ "forall i in t1.first..t1.last "
+ "insert into vertical_design values t1(i);"
+ "end;";
executeSQL(bulkInsert);
}
private void dropAndCreateTable() {
String dropSql = "declare c int;"
+ "begin "
+ "select count(*) into c from user_tables where table_name = upper('v2d_temp');"
+ "if c = 1 then "
+ "truncate table v2d_temp"
+ "drop table v2d_temp;"
+ " end if;"
+ "end;";
executeSQL(dropSql);
String createSql = "CREATE GLOBAL TEMPORARY TABLE v2d_temp (\n"
+ "DEAL_ID NUMBER,\n"
+ "id NUMBER,\n"
+ "karpardaz VARCHAR2(350),\n"
+ "GOOD_TYPE_GROUP VARCHAR2(250 BYTE),\n"
+ "GOOD_CODE VARCHAR2(50 BYTE),\n"
+ "GOOD_TITLE VARCHAR2(250 BYTE),\n"
+ "COUNT NUMBER,\n"
+ "FACTOR_COUNT NUMBER,\n"
+ "GHABZ_COUNT NUMBER,\n"
+ "DEAL_NO VARCHAR2(50 BYTE),\n"
+ "DEAL_DATE DATE,\n"
+ "REQUEST_NO VARCHAR2(50 BYTE),\n"
+ "REQUEST_DATE DATE,\n"
+ "REQUEST_CLIENT VARCHAR2(250 BYTE),\n"
+ "STATUS VARCHAR2(250 BYTE),\n"
+ "TYPE VARCHAR2(250 BYTE),\n"
+ "GEN_SECURITY_DATA_ID NUMBER(10),\n"
+ "MTDREPORT_ID NUMBER\n"
+ ")\n"
+ "ON COMMIT PRESERVE ROWS";
executeSQL(createSql);
}
private void executeSQL(String sql) {
Connection con = null;
try {
con = getConnection();
Statement st = con.createStatement();
st.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
} finally {
if(con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Mon patron insiste pour que je l'utilise de cette façon, tables temporaires et etc. donc je n'ai pas d'autres choix. C'est le deuxième jour, je suis à la recherche d'une autre façon qu'à l'aide de tables temporaires et d'utiliser les données dans d'autres sections, pouvez-vous me guider pour certains d'autres moyens?
Alors que votre patron ne comprends pas comment Oracle fonctionne.
Chercher un autre emploi. Vous n'apprendrez rien de valeur.
peut-être que vous avez raison, mais maintenant, en ce moment, je dois trouver un moyen de résoudre ce problème, il est persistant qu'il y a une manière de le faire, et quand je l'ai expliquer plus en détail qu'il n'y a aucun moyen de le faire par le biais de tables temporaires, je lui fais encore plus en colère, et il est à penser que je ne sais rien à propos de l'oracle! J'ai expliqué plus en détails dans la première réponse de commentaires, si vous avez la moindre idée sur comment puis-je forcer oracle de perdre du temp table sans tenir compte d'autres de la session de données, je serai très reconnaissante si vous le partager avec moi.
OriginalL'auteur Naeem Baghi | 2015-09-06
Vous devez vous connecter pour publier un commentaire.
Oracle de tables temporaires globales ne sont pas des objets transitoires. Ils sont bon tas de tables. Nous créons une fois d'une session pouvez les utiliser pour stocker des données qui n'est visible que pour cette session.
De l'aspect temporaire est que les données n'est pas persistant au-delà d'une transaction ou d'une session. La clé de la mise en œuvre du détail, c'est que les données sont écrites dans un espace de stockage temporaire non permanent. Cependant, les données sont écrites et lues à partir du disque, il est donc notable des frais généraux pour l'utilisation des tables temporaires globales.
Le point est que nous ne sommes pas censés supprimer et recréer les tables temporaires. Si vous essayez de port SQL Server style logique dans Oracle, alors vous devriez envisager l'utilisation de PL/SQL collections de maintenir temporairement des données en mémoire. En savoir plus.
La cause spécifique de
ORA-14452
est que l'on ne peut pas laisser tomber d'une table temporaire globale qui a une portée session persistance si il a contenu de données au cours de la session. Même si le tableau est vide...La solution est de mettre fin à la session et re-connecter, ou (un peu bizarrement) pour tronquer la table et l'y déposer.
Si une autre session à l'aide de la table temporaire globale - et c'est possible (d'où le mondiale de la nomenclature), alors vous ne serez pas en mesure de supprimer la table jusqu'à ce que toutes les sessions de la déconnexion.
Alors que la véritable solution est d'apprendre à utiliser les tables temporaires globales correctement: créer des tables temporaires globales pour correspondre à chaque rapport. Ou, comme je l'ai dit, l'utilisation de PL/SQL les collections de la place. Ou, même, juste apprendre à bien écrire-à l'écoute de SQL. Souvent, nous utilisons des tables temporaires comme une solution à un mal écrit requête qui pourraient être sauvées grâce à un meilleur accès chemin d'accès.
Avoir regardé ton code complet, le flux semble encore plus bizarre:
Il y a donc beaucoup de frais généraux et le gaspillage de l'activité ici. Tout ce que vous devez faire est de prendre les données que vous insérez dans
v2d_temp
et directement remplirvertical_design
, idéalement avec un INSERT ... SELECT * from déclaration. Vous aurez besoin de pré-traitement pour convertir un tableau JSON dans une requête, mais qui est facile à réaliser en Java et PL/SQL.Il me semble certain que les tables temporaires globales ne sont pas la bonne solution pour votre scénario.
Ce que vous avez est un Patron Problème pas un Problème de Programmation. Par conséquent, il est hors-sujet autant que StackOverflow va. Mais voici quelques suggestions de toute façon.
L'essentiel à retenir, c'est que nous ne parlons pas d'un compromis sur certaines sous-optimale de l'architecture: ce que votre patron propose clairement ne fonctionne pas dans un environnement multi-utilisateur. ainsi, vos options sont:
ORA-14452
d'erreur, passez à la production, puis utiliser la "mais vous m'avez dit de" la défense quand tout va mal. C'est la plus faible jeu.ORA-14452
erreur, dites que vous avez fait quelques recherches et il semble que ce est une question fondamentale, avec l'aide de tables temporaires globales dans ce mode, mais de toute évidence, vous avez oublié quelque chose. Ensuite, demandez-leur comment ils ont obtenu autour de ce problème quand ils ont mis en œuvre avant. Cela peut aller de plusieurs façons, peut-être qu'ils ont une solution, peut-être qu'ils vont se rendre compte que ce n'est pas la voie à l'utilisation de tables temporaires globales, peut-être qu'ils vont vous dire de se perdre. De toute façon, c'est la meilleure approche: vous avez soulevé des préoccupations au niveau approprié.Bonne chance.
Les plus de détails que vous fournissez au moins cela semble être un problème qui a besoin de tables temporaires globales. Le fait qu'on vous dit de les utiliser par votre patron veut dire que c'est un problème politique pas la technique, et donc au-delà de notre domaine de compétence.
Je sais que c'est un problème politique, mais ma question est au sujet de trouver une réponse à la question : Est-il possible pour la suppression d'une table temporaire globale qui est dépendante de session dans oracle? Si nous avons une telle façon de faire, mon problème est résolu.
Bien sûr, vous avez été dans une situation comme moi que votre patron ou à d'autres personnes persistent à faire quelque chose de travers de leur chemin, de sorte que vous ne pouvez pas modifier, vous pouvez tout simplement utiliser certains moyens ou quelques astuces pour que vous puissiez faire la chose dans la sale!
OriginalL'auteur APC
Une autre approche mérite d'être examiné ici est à repenser si vous avez besoin d'une table temporaire.
C'est un très commun de la programmation de la pratique parmi ceux qui passent à partir d'autres Sgbdr d'Oracle pour en abuser, parce qu'ils ne comprennent pas que vous pouvez utiliser des fonctionnalités telles que les Expressions de Table Communes implicite de matérialiser un résultat temporaire qui peut être référencé dans d'autres parties de la même requête, et sur d'autres systèmes, il est devenu naturel d'écrire des données dans un tableau, puis sélectionnez.
L'échec est généralement aggravée par le fait de ne pas comprendre que PL/SQL, ligne par ligne de traitement est inférieure à presque tous les égards à SQL base de traitement de l'ensemble -- plus lent, plus complexe à code, plus verbeux, et plus enclins à faire des erreurs-mais Oracle présente donc de nombreuses autres fonctionnalités puissantes pour le traitement SQL que même lorsqu'il est requis, il peut généralement être intégré directement dans une instruction SQL SELECT de toute façon.
Comme une note, en 20 ans d'écriture Oracle code pour le reporting et l'ETL, j'ai seulement besoin de faire usage de ligne-par-ligne de traitement une fois, et jamais eu besoin d'utiliser une table temporaire.
OriginalL'auteur David Aldridge
Tuer des sessions est la seule façon de contourner ORA-14452 erreurs. Utiliser le dictionnaire de données pour trouver d'autres sessions à l'aide de la table temporaire et de les tuer
avec une instruction comme
alter system kill session 'sid,seriall#,instance_id';
.C'est le "officielle" de la solution mentionnée dans le support d'Oracle document
La FAÇON DE DIAGNOSTIQUER UN ORA-14452 PENDANT la CHUTE DE la TABLE TEMPORAIRE (Doc ID 800506.1). J'ai utilisé avec succès cette méthode dans le passé, pour une raison légèrement différente.
Tuer des sessions requiert des privilèges élevés et peut être difficile; il peut exiger de tuer, d'attente, et d'essayer de nouveau plusieurs fois.
Cette solution est presque certainement une mauvaise idée pour plusieurs raisons. Avant d'implémenter cela, vous devriez essayer de tirer parti de cette information comme preuve que ce n'est
la mauvaise façon de le faire. Par exemple, "documentation d'Oracle dit que cette méthode nécessite
alter system
privilège, ce qui est dangereux et soulève quelquesles questions de sécurité...".
Oh oui, tuant des séances est très dangereux et peuvent causer toutes sortes de problèmes. Il est extrêmement rare d'avoir une demande de tuer des séances. C'est la seule façon de faire ce travail mais je ne suis pas vraiment en vous proposant des faire. Au lieu de cela, vous pourriez en parler à votre DBA; ils ne sera probablement insister pour vous de trouver une autre approche.
heureusement, cette tâche est hors de moi, et il a attribué à une autre personne, il a constaté que cela ne peut pas arriver trop, de sorte que nous allons discuter à nouveau pour changer la façon dont nous voulons mettre en œuvre cette tâche
OriginalL'auteur Jon Heller
Vous pouvez voir toutes les sessions en cours d'exécution en cours d'exécution:
Pour tuer une session, vous avez quelques options. La commande suivante attend le courant en vol les transactions à terminer avant de déconnecter:
Alors que la commande suivante est comme kill -9; il essuie les O/S processus:
La dernière est la plus efficace dans le meurtre de la session qui vous empêchent de vous retirer d'une table temporaire. Toutefois, à utiliser avec prudence, car il est d'une jolie force brute de la fonction. Une fois la session terminée, vous pouvez supprimer le temp de table sans avoir des erreurs.
Vous pouvez en savoir plus sur les différentes façons de tuer une session ici (je ne suis pas affilié à ce site, je suis tombé sur moi-même quand j'ai eu un problème similaire au vôtre):
https://chandlerdba.wordpress.com/2013/07/25/killing-a-session-dead/
OriginalL'auteur dearsina