一、ORA-00955 報錯究竟為何?

(一)含義解讀
在使用 Oracle 數據庫時,大家可能會遇到 ORA-00955 這樣的報錯提示,它所代表的含義是 “名稱已由現有對象使用”。簡單來說呢,就是你在進行數據庫相關操作,想要創建某個對象(比如表、視圖等),或者對某些對象進行特定操作時,所使用的這個對象名稱,在當前數據庫環境里已經被別的對象占用了,這就導致了該報錯的出現,讓操作沒辦法順利進行下去哦。
(二)常見出現場景
創建視圖時:例如在執行 “create or replace view csews as select * from order_list;” 這樣的語句創建視圖時,可能會出現 ORA-00955 報錯。有可能是數據庫中已經存在了名為 “csews” 的對象,像有人之前創建過同名的同義詞等情況,即便去查詢 “select * from all_objects where object_name=‘csews‘;” 可能一時沒查出來(有時需要將名稱換成大寫去查詢,因為經過 Oracle 的詞法分析,本身會將小寫轉成大寫),就會導致創建視圖時出現這個報錯啦。只有把同名的已有對象(如刪除對應的同義詞 “drop public synonym CSEWS;”)處理掉,才能成功創建視圖哦。創建表時:很多小伙伴在建表過程中也常常遇到這個報錯呢。有時候以為換個表名稱就行了,可實際并非如此簡單呀。比如在建表語句里,不僅是表名不能和已有的重復,像主鍵名等一些相關的約束名如果和以前的相同,也會造成無法進行創建表的操作哦。就像執行 “create table EXIST_OBJECT (SNO VARCHAR2 (100) NULL,NAME VARCHAR2 (255) NULL);” 這樣的語句創建表時,可能會報 ORA-00955 錯誤,要是查詢對象時沒找到重復對象,還需要進一步去排查是不是其他相關命名沖突等情況呢。刪除用戶時:在刪除用戶操作中,如果該用戶名下有一些對象(像表、視圖等),而這些對象的名稱和其他用戶或者系統中已有的對象重名了,那么在執行刪除用戶這個動作時,也有可能觸發 ORA-00955 報錯哦。因為數據庫要確保對象名稱的唯一性,當存在這種重名情況時,就需要先去處理好重名對象的相關問題,才能順利刪除用戶呢。創建物化視圖時:比如在目標庫上創建定時增量更新的物化視圖,像執行 “create materialized view PF_ALARM_TYPE refresh fast on demand start with sysdate next sysdate+1/288 with rowid as select * from PF_ALARM_TYPE@SGUAP_LINK;” 語句時,要是創建的物化視圖名稱和已有的表名相同了,那就會出現 ORA-00955 報錯,此時可以選擇修改物化視圖的名稱或者把那個同名的表刪除(不過刪除表操作得謹慎哦),來解決這個報錯問題,以便成功創建物化視圖呀。創建無參數存儲過程時:在創建無參數存儲過程時,如果重復運行創建語句(已經先運行過一次了),又沒有添加 “or replace”(這個的意思是:沒有該名稱過程時創建一個新的過程;有該名稱過程時,將原先的過程覆蓋),也會出現 “名稱已由現有對象使用” 這個 ORA-00955 報錯呢,修改代碼添加 “or replace” 后,往往就能正常執行啦。
二、ORA-00955 報錯原因大揭秘
(一)對象重名問題
在 Oracle 數據庫的操作中,對象重名是引發 ORA-00955 報錯的一個常見原因哦。這里所說的對象涵蓋了諸多方面,比如表名、視圖名、索引名等等。當我們執行創建對象的操作時,數據庫會先去核查即將創建的這個對象名稱是否已經存在于當前的數據庫環境里了。舉個例子呀,要是執行 “create global temporary table temp_aud on commit preserve rows as select * from sys.dba_audit_trail;” 這樣的語句來創建臨時表,結果報了 ORA-00955 錯誤,很有可能就是存在一個視圖和這個要創建的臨時表重名啦。這時候呢,我們可以通過 “select a.OBJECT_type,a.* from all_objects a where upper (a.OBJECT_NAME) ='TEMP_AUD';” 這樣的查詢語句去查看重名的對象哦。要是查出來有重名對象,解決方法要么是修改我們準備創建的這個對象的名稱,要么就是刪掉那個重復的已有對象呀。不過需要注意的是,如果查詢對象時沒有找到重復的呢,還可以在 dba 賬戶下執行 “alter system flush shared_pool;” 語句刷新一下共享池試試哦,但這個方法不一定每次都能解決問題啦。再比如創建表的時候,執行 “create table EXIST_OBJECT (SNO VARCHAR2 (100) NULL,NAME VARCHAR2 (255) NULL);” 語句創建表,出現 ORA-00955 報錯,去查詢對象時卻沒找到重復對象,那還得進一步排查是不是其他相關命名沖突等情況呢,因為不光是表名本身不能重復,像主鍵名等一些相關的約束名如果和以前的相同,也會導致這個報錯出現,進而沒辦法順利創建表哦??傊?,只要創建的對象名稱與數據庫里已有的對象重名了,就大概率會觸發 ORA-00955 報錯,操作也就沒法繼續進行下去啦。
(二)命名規范缺失隱患
很多時候,出現 ORA-00955 報錯是因為缺乏合理的命名策略,隨意命名而導致了標識符沖突呢。大家在給數據庫里的對象命名時呀,如果沒有一個統一規范的標準,很容易就出現問題哦。比如說在給表命名的時候,典型的命名約定是給它一個描述性的名稱,并且最好保持格式上的一致性,像可以統一使用單數冠詞(比如 “customer” 或 “facility” )或者復數冠詞(比如 “customers” 或 “facilities”)來命名呀。在給列命名時呢,同樣要給它一個描述性的名稱,除非受到字符限制,否則盡量不要使用縮寫哦,要是用了縮寫,也可以在該列上添加注釋來提供完整的詳細信息嘛,而且一般不需要在列名中包括表名,畢竟這屬于多余的信息,開發人員每次使用該列時還得多輸入額外的字符呢。還有在命名約束時呀,要給它一個能清楚標識其位置和內容的描述性名稱哦,通常要涉及到約束的類型(因為表的一列可以有多個約束呀)、表名(可能存在多個表,每個表有相同的列名這種情況哦)以及列名(同一個表中,不同的列上可能有多個相同類型的約束呢)。像約束名稱常見的公式可以是 “tablename_columnname_(pk|fk|u|nn|chk)” 或者 “(pk|fk|u|nn|chk)_tablename_columnname”(具體用哪種取決于咱們在搜索約束時希望將表名還是約束類型作為對約束進行排序的主要標準啦)。要是不遵循這些命名規范,隨意去給對象命名,就很容易出現標識符沖突,進而引發 ORA-00955 報錯啦。所以呀,大家一定要重視命名規范的重要性,在整個數據庫的操作過程中,始終如一地應用合理的命名策略,這樣才能減少這類報錯情況的出現哦。
三、ORA-00955 報錯的解決辦法有哪些?
(一)常規處理手段
當遇到 ORA-00955 報錯時,我們可以先嘗試一些常規的處理手段哦。比如刷新共享池,當你去查詢對象時沒有找到重復對象,就可以在 dba 賬戶下執行 “alter system flush shared_pool;” 語句來刷新一下共享池試試呀。操作步驟如下:首先登陸數據庫服務器,輸入 “su - oracle”,接著進入 “sqlplus "/as sysdba"”,然后執行 “alter system flush shared_pool;”,最后輸入 “exit” 退出就可以啦。不過要注意哦,這個方法不一定每次都能解決問題呢。還有就是刪除重復對象啦,如果通過查詢(像使用 “select a.OBJECT_type,a.* from all_objects a where upper (a.OBJECT_NAME) =' 具體對象名稱 ';” 這樣的語句去查詢)確定存在重復的對象,那根據實際情況把重復的對象刪掉就行啦。例如創建視圖時發現有同名的同義詞導致報錯,那就可以執行 “drop public synonym 同義詞名稱;” 來刪掉這個重復對象,從而順利創建視圖哦。另外,修改名稱也是常用的辦法呢。像在創建物化視圖時,要是名稱和已有的表名相同了出現報錯,這時候可以選擇修改物化視圖的名稱,避免和已有的對象重名,進而解決 ORA-00955 報錯問題,成功進行相應的創建操作呀??傊剑@些常規處理手段在很多常見的 ORA-00955 報錯場景中都可以先嘗試一下,說不定就能快速解決問題,讓操作繼續順利進行下去哦。
(二)復雜情況應對
但有時候我們會遇到比較復雜的情況呢,比如臨時表被鎖了。下面就來講講針對這類復雜情況該怎么應對哈。首先要查找正在使用相關對象的會話,以臨時表為例,我們可以通過以下步驟來查找哦。先執行 “select object_id from user_objects where object_name=upper (' 具體臨時表名稱 ');” 查出對象的 id,接著執行 “select sid from v session where sid = 前面查到的 sid;”,不過要是存在多個可能沒辦法直接查詢,那就按照這樣的分步查詢來操作哦。查到相關會話后,就要殺掉進程啦,使用 “alter system kill session'sid,serial#';” 語句來進行操作。但有可能會出現 ORA-00031 報錯,這代表在數據庫級不能馬上殺掉該死鎖進程,不過它已經被標記為待殺掉的狀態了,會在其當前不可中斷的操作完成后盡快被終止哦,要是想讓它更快被終止,也可以再次執行這個殺掉進程的命令呢。要是出現上述情況,還需要在操作系統級進行處理哦。先通過 “select spid, osuser, s.program from v process p where s.paddr = p.addr and s.sid = 具體的 sid;” 查出這個 session 的 spid,然后在數據庫服務器上使用 “kill -9 spid”(這里的 spid 就是前面查出來的值哦)殺掉查出的系統進程,并用 root 用戶再執行這個操作確保進程被徹底殺掉呢。通過這樣一系列在數據庫級和操作系統級的處理流程,即便遇到像臨時表被鎖這類棘手的復雜情況,咱們也能嘗試去應對解決 ORA-00955 報錯問題,讓數據庫操作恢復正常呀。
四、如何有效預防 ORA-00955 報錯?
(一)合理規劃命名
在數據庫操作的世界里呀,提前做好規劃可是相當重要的呢,尤其是針對各類對象的命名規劃哦。咱們得制定一套統一、規范的命名規則,這能從源頭上避免很多因命名問題而引發的 ORA-00955 報錯情況哦。就拿數據庫里常見的表、列、約束等對象來說吧。在給表命名時呀,建議采用一些描述性的名稱,并且保持格式上的一致性哦,像可以統一使用單數冠詞(比如 “customer” 或 “facility” )或者復數冠詞(比如 “customers” 或 “facilities”)來命名呢。例如咱們要創建一個存儲客戶信息的表,就可以命名為 “customers”,讓人一眼就能大概知道這個表的用途啦。對于列的命名呢,同樣也得給它一個清晰明了的描述性名稱哦,除非受到字符限制,否則盡量不要使用縮寫呀。要是實在用了縮寫,那不妨在該列上添加注釋來提供完整的詳細信息嘛,而且呀,一般不需要在列名中包括表名哦,畢竟這屬于多余的信息,要是每次開發人員使用該列時還得多輸入額外的字符,多麻煩呀。比如說有個 “customers” 表,里面存儲客戶電話號碼的列,咱們可以命名為 “phone_number”,而不是 “customers_phone” 哦。還有約束的命名也不容忽視哦,要給它一個能清楚標識其位置和內容的描述性名稱呢,通常要涉及到約束的類型(因為表的一列可以有多個約束呀)、表名(可能存在多個表,每個表有相同的列名這種情況哦)以及列名(同一個表中,不同的列上可能有多個相同類型的約束呢)。像約束名稱常見的公式可以是 “tablename_columnname_(pk|fk|u|nn|chk)” 或者 “(pk|fk|u|nn|chk)_tablename_columnname”(具體用哪種取決于咱們在搜索約束時希望將表名還是約束類型作為對約束進行排序的主要標準啦)??傊?,只有提前合理規劃好這些命名規則,并且在整個數據庫操作過程中始終如一地去應用它,才能最大程度減少因為命名不當而出現 ORA-00955 報錯的可能性哦,小伙伴們可一定要重視起來呀。
(二)操作前仔細檢查
在進行數據庫的各種操作,像創建、修改等動作之前呀,咱們可得多留個心眼,仔細地對要操作的對象名稱進行檢查核對哦,這一步可是能幫咱們減少不少 ORA-00955 報錯出現的幾率呢。比如說咱們準備創建一個新的視圖或者表的時候呀,不要著急著去執行創建語句哦,先停下來,通過相應的查詢語句去確認一下即將使用的這個對象名稱是不是已經存在于當前的數據庫環境里啦。像可以使用 “select a.OBJECT_type,a.* from all_objects a where upper (a.OBJECT_NAME) =' 具體對象名稱 ';” 這樣的語句去查詢一下哦。要是發現存在重名風險,那就得趕緊想辦法解決啦,要么修改咱們準備創建的這個對象的名稱,換個獨特的、還沒被使用過的名字呀;要么呢,如果確定是之前遺留的一些重復的、已經不需要的對象,就可以把它刪掉哦,比如創建視圖時發現有同名的同義詞導致報錯,那就可以執行 “drop public synonym 同義詞名稱;” 來刪掉這個重復對象,從而順利進行后續的創建操作啦。再比如在設置將表的字段設置為自增,用序列 sequence 的方法來實現時,此時要特別留意 sequence 后的名字要和創建表時的名字不一致哦,要是先前已經寫了一樣的名字,可以在 PL/SQL 軟件中找到 Sequence,找到對應的刪除,然后重新運行(如果是表名先建立,可以使用 “drop table 表名;” 進行刪除)呢。所以呀,操作前這簡單的檢查核對步驟可千萬別偷懶省略哦,它能讓咱們后續的數據庫操作更加順暢,少被 ORA-00955 報錯這類問題所