Wednesday, June 29, 2011

Script to Purge All Objects for a User in Oracle

I have to purge and reload an Oracle Database dump on a monthly basis. I have been manually deleting all of the Objects with Toad before loading the new dump. I searched for a script that would delete all of the objects. Many people suggested that you should just drop the user, but if I do this I have to add back in grants that don't get picked up by the export.

This thread on the Oracle Discussion Forum has several solutions. I am pasting the script that worked the best for me below from Massimo. There is some criticism in the thread about why he did not just use the object name in one case instead of all the If/Else conditions; however, I like this approach better, because I can easily take out something if I need to:

stringa varchar2(100);

cursor cur is
select *
from user_objects;

for c in cur loop
stringa := '';
if c.object_type = 'VIEW' then
stringa := 'drop view ' || c.object_name;
EXECUTE immediate stringa;
elsif c.object_type = 'TABLE' then
stringa := 'drop table ' || c.object_name || ' cascade constraints';
EXECUTE immediate stringa;
elsif c.object_type = 'SEQUENCE' then
stringa := 'drop sequence ' || c.object_name;
EXECUTE immediate stringa;
elsif c.object_type = 'PACKAGE' then
stringa := 'drop package ' || c.object_name;
EXECUTE immediate stringa;
elsif c.object_type = 'TRIGGER' then
stringa := 'drop trigger ' || c.object_name;
EXECUTE immediate stringa;
elsif c.object_type = 'PROCEDURE' then
stringa := 'drop procedure ' || c.object_name;
EXECUTE immediate stringa;
elsif c.object_type = 'FUNCTION' then
stringa := 'drop function ' || c.object_name;
EXECUTE immediate stringa;
elsif c.object_type = 'SYNONYM' then
stringa := 'drop synonym ' || c.object_name;
EXECUTE immediate stringa;
elsif c.object_type = 'INDEX' then
stringa := 'drop index ' || c.object_name;
EXECUTE immediate stringa;
elsif c.object_type = 'PACKAGE BODY' then
stringa := 'drop PACKAGE BODY ' || c.object_name;
EXECUTE immediate stringa;
elsif c.object_type = 'DATABASE LINK' then
stringa := 'drop database link ' || c.object_name;
EXECUTE immediate stringa;
end if;
when others then
end loop;
-- PURGE recyclebin


Tuesday, June 28, 2011

Convert char[] to String in c#

If you have something like:

char [] chArray = infile.ReadChars(10);


char[] chArray = new char[] {'t','e','s','t'};

and you want to convert it to a String, I always (incorrectly) try:

String str = chArray.ToString();

and it doesn't work (you get "System.Char[]").

You have to say something like this:

String str = new String(chArray);

Sunday, June 26, 2011

Importing a Datapump export into Oracle with IMPDP

I never had to remember the command-line options for the old imp utility (because it prompted you for the info it needed), but with impdp, you need to know what to specify. Here is my simple example that works for me to import a Datapump export file:

impdp user/password schemas=mySchema dumpfile=myfile.dpdmp logfile=mylog.log

The schema parameter specifies which schema from the file to import.

The dumpfile parameter specifies the name of the datapump export file to import. The catch here is that the dump file location defaults to a default directory on the server (something like this):


You can change this path, but you have to create the directory in Oracle and specify it with a Directory Parameter. You have to create a directory in Oracle with something like this:

create directory MyExportDir as 'c:\exports';

Here is the detailed info for impdp on the Oracle site.

Creating a Tablespace in Oracle with SQL

I never can seem to remember the SQL to create a tablespace in Oracle. I am posting my example that I use to I can easily find it again in the future:

create tablespace MyTableSpaceName
datafile 'MyTableSpaceFile.dbf'
size 32m
autoextend on
next 32m maxsize unlimited
extent management local;

Oracle Function to Read SDO_ORDINATE Values without causing Exception in .NET

Below is an Oracle function to read a specified SDO_ORDINATE value in an SDO_GEOMETRY attribute so that ODP.NET can handle them without causing an Arithmetic Overflow Exception in .NET when the Oracle NUMBER value has too many digits after the decimal place for a .NET Decimal value.

Most of this function comes from this thread on the Oracle Discussion Forum:

CREATE OR REPLACE function Get_Ordinate_Value(geom sdo_geometry, vPos number default 1) return number

if geom is null
return null;
end if;

if vPos <1 or vPos >geom.sdo_ordinates.count()
return null;
end if;

return round(geom.sdo_ordinates(vPos ),8);

Using the Function is something like this where I am getting the origin point and orientation vector for a 3D Oriented Point geometry:

select Get_Ordinate_Value(MyGeomAttr,1) as X,
Get_Ordinate_Value(MyGeomAttr,2) as Y,
Get_Ordinate_Value(MyGeomAttr,3) as Z,
Get_Ordinate_Value(MyGeomAttr,4) as AngleX,
Get_Ordinate_Value(MyGeomAttr,5) as AngleY,
Get_Ordinate_Value(MyGeomAttr,6) as AngleZ
from MyTable

This function is pretty simple. I first check to see if the geometry attribute is Null and return Null if it is. I found that if I did not do this, you will get a geometry attribute that is Null passed into the function and you get a "ORA-06531: Reference to uninitialized collection" and it is sometimes hard to tell where it is coming from.

Then the index is checked to see that it is in range for the SDO_ORDINATE array.

I finally use the Round function to reduce the number of digits after the decimal point to a number that the .NET Decimal type can handle.

How to use SQL to retrieve the Vertex values in an SDO_GEOMETRY Attribute

It turns out to be more complicated than you might think to simply retrieve the Vertices of an SDO_GEOMETRY attribute in Oracle Spatial using just SQL. The main problem is that this is an array of an unknown size, so the solution below is just for retrieving the Ordinate values for 1 record identified by a key and each record returned is one Ordinate in the list.

FROM MyTable a
WHERE MyKey=24974)

which will retrieve something like this (my example uses a 3D geometry so there are 3 value per vertex with Z being 0 in all of them):

I will go through why I did the things I did to make this work like I wanted below.

If you are using ODP.NET and you have Oracle Number values in the Ordinates that are larger than a .NET Decimal value (this is common for me), you must use Round (or truncate the value in someway) so that you don't get an Arithmetic Overflow when the Ordinate Value is loaded into a .NET decimal value. I am using the Round function to simply get 8 decimal points of precision). It turns out that the data I have uses Oriented Points and the computed vector coordinates use a large number of decimal places that .NET Decimals can't handle.

To get the Ordinate Values back as the Query results, you must use the TABLE function to convert the SDO_ORDINATES Array to records. See here for more info on the TABLE function. The key thing here is that the COLUMN_VALUE is not just me making up a name for my example, it is a keyword that lets you refer to the value the Table function returns (otherwise you can't run the results of the Table function through the Round function).

The alias "a" seems to be required or you get an error in the query.

Counting Unique (Distinct) Records with SQL

Using SQL to count all records in a table:

select count(*) from MyTable

Using SQL to count all records in a table with unique/distinct values in a particular attribute:

select count(distinct MyId) from MyTable

Wednesday, June 22, 2011

Auto-Incrementing Assembly and File version in Visual Studio

I made a post on this topic some time ago. I still find it incredible that Visual Studio (2005, 2008, 2010) doesn't provide a way to automatically increment the File Version number in an Assembly. Why is this important? To me, the Setup and Deployment project will not deliver a file if the file version is the same (even if the file is newer, different, etc.). It is very easy to forget to go manually update the assembly's File Version, and you don't find out about it until your users install the updated application and see no difference.

The method I posted before works fine, but it is a little complicated to setup and get going.

The new method I found is much easier to setup and use: