Quantcast
Channel: sqlcl | ThatJeffSmith
Viewing all 123 articles
Browse latest View live

Generating Table DDL via SQLcl, with and without Storage Clauses

$
0
0

We’re getting much closer to having Oracle SQL Developer version 4.1 ready for release – which includes SQLcl, our new command-line interface for Oracle Database.

Just a quick reminder in case you’re too lazy to click to that other post:

We’ve taken our existing Java based SQL*Plus script engine from SQL Developer, and built a new command line interface that does most of what SQL*Plus offers plus adds a bunch of cool GUI features from SQL Developer. We’re calling this new program, SQLcl.

One of the new commands is DDL.

 
SQL> ddl hr.employees
 
  CREATE TABLE "HR"."EMPLOYEES"
   (    "EMPLOYEE_ID" NUMBER(6,0),
        "FIRST_NAME" VARCHAR2(20),
        "LAST_NAME" VARCHAR2(25) CONSTRAINT "EMP_LAST_NAME_NN" NOT NULL ENABLE,
        "EMAIL" VARCHAR2(25) CONSTRAINT "EMP_EMAIL_NN" NOT NULL ENABLE,
        "PHONE_NUMBER" VARCHAR2(20),
        "HIRE_DATE" DATE CONSTRAINT "EMP_HIRE_DATE_NN" NOT NULL ENABLE,
        "JOB_ID" VARCHAR2(10) CONSTRAINT "EMP_JOB_NN" NOT NULL ENABLE,
        "SALARY" NUMBER(8,2),
        "COMMISSION_PCT" NUMBER(2,2),
        "MANAGER_ID" NUMBER(6,0),
        "DEPARTMENT_ID" NUMBER(4,0),
         CONSTRAINT "EMP_SALARY_MIN" CHECK (salary > 0) ENABLE,
         CONSTRAINT "EMP_EMAIL_UK" UNIQUE ("EMAIL")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  TABLESPACE "USERS"  ENABLE,
         CONSTRAINT "EMP_EMP_ID_PK" PRIMARY KEY ("EMPLOYEE_ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  TABLESPACE "USERS"  ENABLE,
         CONSTRAINT "EMP_DEPT_FK" FOREIGN KEY ("DEPARTMENT_ID")
          REFERENCES "HR"."DEPARTMENTS" ("DEPARTMENT_ID") ENABLE,
         CONSTRAINT "EMP_JOB_FK" FOREIGN KEY ("JOB_ID")
          REFERENCES "HR"."JOBS" ("JOB_ID") ENABLE,
         CONSTRAINT "EMP_MANAGER_FK" FOREIGN KEY ("MANAGER_ID")
          REFERENCES "HR"."EMPLOYEES" ("EMPLOYEE_ID") ENABLE
   ) SEGMENT CREATION IMMEDIATE
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
 NOCOMPRESS LOGGING
  TABLESPACE "USERS"
 
   COMMENT ON COLUMN "HR"."EMPLOYEES"."EMPLOYEE_ID" IS 'Primary key of employees table.'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."FIRST_NAME" IS 'First name of the employee. A not null column.'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."LAST_NAME" IS 'Last name of the employee. A not null column.'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."EMAIL" IS 'Email id of the employee'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."PHONE_NUMBER" IS 'Phone number of the employee; includes country code and area code'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."HIRE_DATE" IS 'Date when the employee started on this job. A not null column.'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."JOB_ID" IS 'Current job of the employee; foreign key to job_id column of the
jobs table. A not null column.'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."SALARY" IS 'Monthly salary of the employee. Must be greater
than zero (enforced by constraint emp_salary_min)'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."COMMISSION_PCT" IS 'Commission percentage of the employee; Only employees in sales
department elgible for commission percentage'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."MANAGER_ID" IS 'Manager id of the employee; has same domain as manager_id in
departments table. Foreign key to employee_id column of employees table.
(useful for reflexive joins and CONNECT BY query)'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."DEPARTMENT_ID" IS 'Department id where employee works; foreign key to department_id
column of the departments table'
   COMMENT ON TABLE "HR"."EMPLOYEES"  IS 'employees table. Contains 107 rows. References with departments,
jobs, job_history tables. Contains a self reference.'
 
  CREATE INDEX "HR"."EMP_DEPARTMENT_IX" ON "HR"."EMPLOYEES" ("DEPARTMENT_ID")
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  TABLESPACE "USERS"
 
  CREATE INDEX "HR"."EMP_JOB_IX" ON "HR"."EMPLOYEES" ("JOB_ID")
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  TABLESPACE "USERS"
 
  CREATE INDEX "HR"."EMP_MANAGER_IX" ON "HR"."EMPLOYEES" ("MANAGER_ID")
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  TABLESPACE "USERS"
 
  CREATE INDEX "HR"."EMP_NAME_IX" ON "HR"."EMPLOYEES" ("LAST_NAME", "FIRST_NAME")
  PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  TABLESPACE "USERS"
 
  CREATE OR REPLACE EDITIONABLE TRIGGER "HR"."UPDATE_JOB_HISTORY"
  AFTER UPDATE OF job_id, department_id ON employees
  FOR EACH ROW
BEGIN
  add_job_history(:OLD.employee_id, :OLD.hire_date, sysdate,
                  :OLD.job_id, :OLD.department_id);
END;
ALTER TRIGGER "HR"."UPDATE_JOB_HISTORY" ENABLE
 
  CREATE OR REPLACE EDITIONABLE TRIGGER "HR"."SECURE_EMPLOYEES"
  BEFORE INSERT OR UPDATE OR DELETE ON employees
BEGIN
  secure_dml;
END secure_employees;
ALTER TRIGGER "HR"."SECURE_EMPLOYEES" DISABLE

Woohoo! But I don’t need that icky STORAGE stuff

So turn it off.

We’re calling DBMS_METADATA under the covers to generate this DDL. And you can tell that package exactly how you want your DDL generated. The command is pretty simple, but it’s a bit verbose for me to type, much less to remember.

So I created my own command to toggle this on and off. Well, two commands to be honest.

How do you create your own ‘commands?’ Use the ALIAS feature.

ALIAS new_commmand=code

You can feed one or more parameters to your command, and you can execute one or more statements. Mine are very simple.

Now I can just run this new command to turn storage clauses off for my DDL.

Now I can just run this new command to turn storage clauses off for my DDL.

SQL> dd_storage_off
Command=dd_storage_off
 
PL/SQL PROCEDURE successfully completed.
 
SQL> ddl hr.employees
 
  CREATE TABLE "HR"."EMPLOYEES"
   (    "EMPLOYEE_ID" NUMBER(6,0),
        "FIRST_NAME" VARCHAR2(20),
        "LAST_NAME" VARCHAR2(25) CONSTRAINT "EMP_LAST_NAME_NN" NOT NULL ENABLE,
        "EMAIL" VARCHAR2(25) CONSTRAINT "EMP_EMAIL_NN" NOT NULL ENABLE,
        "PHONE_NUMBER" VARCHAR2(20),
        "HIRE_DATE" DATE CONSTRAINT "EMP_HIRE_DATE_NN" NOT NULL ENABLE,
        "JOB_ID" VARCHAR2(10) CONSTRAINT "EMP_JOB_NN" NOT NULL ENABLE,
        "SALARY" NUMBER(8,2),
        "COMMISSION_PCT" NUMBER(2,2),
        "MANAGER_ID" NUMBER(6,0),
        "DEPARTMENT_ID" NUMBER(4,0),
         CONSTRAINT "EMP_SALARY_MIN" CHECK (salary > 0) ENABLE,
         CONSTRAINT "EMP_EMAIL_UK" UNIQUE ("EMAIL")
  USING INDEX  ENABLE,
         CONSTRAINT "EMP_EMP_ID_PK" PRIMARY KEY ("EMPLOYEE_ID")
  USING INDEX  ENABLE,
         CONSTRAINT "EMP_DEPT_FK" FOREIGN KEY ("DEPARTMENT_ID")
          REFERENCES "HR"."DEPARTMENTS" ("DEPARTMENT_ID") ENABLE,
         CONSTRAINT "EMP_JOB_FK" FOREIGN KEY ("JOB_ID")
          REFERENCES "HR"."JOBS" ("JOB_ID") ENABLE,
         CONSTRAINT "EMP_MANAGER_FK" FOREIGN KEY ("MANAGER_ID")
          REFERENCES "HR"."EMPLOYEES" ("EMPLOYEE_ID") ENABLE
   )
 
   COMMENT ON COLUMN "HR"."EMPLOYEES"."EMPLOYEE_ID" IS 'Primary key of employees table.'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."FIRST_NAME" IS 'First name of the employee. A not null column.'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."LAST_NAME" IS 'Last name of the employee. A not null column.'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."EMAIL" IS 'Email id of the employee'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."PHONE_NUMBER" IS 'Phone number of the employee; includes country code and are
   COMMENT ON COLUMN "HR"."EMPLOYEES"."HIRE_DATE" IS 'DATE WHEN the employee started ON this job. A NOT NULL COLUMN.
   COMMENT ON COLUMN "HR"."EMPLOYEES"."JOB_ID" IS 'Current job of the employee; foreign key to job_id column of the
jobs table. A not null column.'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."SALARY" IS 'Monthly salary of the employee. Must be greater
than zero (enforced by constraint emp_salary_min)'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."COMMISSION_PCT" IS 'Commission percentage of the employee; Only employees in
department elgible for commission percentage'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."MANAGER_ID" IS 'Manager id of the employee; has same domain as manager_id in
departments table. Foreign key to employee_id column of employees table.
(useful for reflexive joins and CONNECT BY query)'
   COMMENT ON COLUMN "HR"."EMPLOYEES"."DEPARTMENT_ID" IS 'Department id where employee works; foreign key to departm
column of the departments table'
   COMMENT ON TABLE "HR"."EMPLOYEES"  IS 'employees table. Contains 107 rows. References with departments,
jobs, job_history tables. Contains a self reference.'
 
  CREATE INDEX "HR"."EMP_DEPARTMENT_IX" ON "HR"."EMPLOYEES" ("DEPARTMENT_ID")
 
 
  CREATE INDEX "HR"."EMP_JOB_IX" ON "HR"."EMPLOYEES" ("JOB_ID")
 
 
  CREATE INDEX "HR"."EMP_MANAGER_IX" ON "HR"."EMPLOYEES" ("MANAGER_ID")
 
 
  CREATE INDEX "HR"."EMP_NAME_IX" ON "HR"."EMPLOYEES" ("LAST_NAME", "FIRST_NAME")
 
 
  CREATE OR REPLACE EDITIONABLE TRIGGER "HR"."UPDATE_JOB_HISTORY"
  AFTER UPDATE OF job_id, department_id ON employees
  FOR EACH ROW
BEGIN
  add_job_history(:OLD.employee_id, :OLD.hire_date, sysdate,
                  :OLD.job_id, :OLD.department_id);
END;
ALTER TRIGGER "HR"."UPDATE_JOB_HISTORY" ENABLE
 
  CREATE OR REPLACE EDITIONABLE TRIGGER "HR"."SECURE_EMPLOYEES"
  BEFORE INSERT OR UPDATE OR DELETE ON employees
BEGIN
  secure_dml;
END secure_employees;
ALTER TRIGGER "HR"."SECURE_EMPLOYEES" DISABLE
SQL>

You can find all of the TRANSFORM procedure options here for defining how you want your DDL generated.

And of COURSE we support spool, so if I want a script file of a table without storage parameters, I just run…

dd_storage_off
spool c:\scripts\employeees_no_storage.sql
ddl hr.employees
spool off
dd_storage_on

SQLcl: Run a Query Over and Over, Refresh the Screen

$
0
0

I was going to talk about our new IMPORT command in SQLcl. This will allow you to feed a delimited text file of data to our command line interface and have it automatically imported to a table.

But Kris Rice beat me to it. Woo-hoo, less work for me :)

So go read that now.

If you read far enough, you’ll see a really cool video on how to create a session monitor in SQLcl.

By the way, we updated it, and have a new EA build for you to play with. DOWNLOAD IT NOW

I’m going to show a simpler example – just a timer using SYSTIMESTAMP.

SET sqlformat ansiconsole
SELECT systimestamp FROM dual;
repeat 15 0.55

Run that.

And you’ll get this.

Pretty cool, huh?

Just run your query – that will put it into the buffer. As in, if I hit ‘/’ – it will run again.

You can also put a query into the buffer using the history command.

Saying ‘history 2′ would put the 2nd item in your SQL History into the buffer.

You're gonna love, love, love the history command in SQLcl

You’re gonna love, love, love the history command in SQLcl

Then run the repeat command.

Tailing the Alert Log with SQLcl

$
0
0

Hopefully you’ve heard about the new SQL*Plus we’re building.

And hopefully you’ve heard about the new REPEAT command we put into it yesterday.

Here’s a quick example of how to build a little ‘monitor’ in just 2 commands, a total of 5 lines of code.

The SQL

SELECT To_Char(Originating_Timestamp, 'DD-MON-YYYY HH24:MI:SSxFF') Time_Entry,
       substr(message_text, 0, 75) || '...' ABBR_MESSAGE_TEXT
FROM X$dbgalertext
ORDER BY Originating_Timestamp DESC
fetch FIRST 10 ROWS ONLY;

So run that, make sure you like the formatting, and the data of course :)

Then to turn that into a refreshing report, run this:

SQL>repeat 100 0.5

And that’s it.

It will run that SQL (as it was the last thing in my SQLcl buffer), 100 times, every 0.5 seconds.

The screen refreshes with an update of what iteration you’re on.

I’ve also set the sqlformat to ANSICONSOLE for the nicer auto-spacing and column headers.

Your SQL is probably better than mine, but this is still pretty cool.

Your SQL is probably better than mine, but this is still pretty cool.

What, you want an animated demo?

Ok, ok.

Here I’m causing some Alert Log entries to be added by forcing a log switch on the Container database.

A half-second refresh, for 100 iterations, so this would run for 50 seconds. I think.

A half-second refresh, for 100 iterations, so this would run for 50 seconds. I think.

About that FETCH FIRST 10 ROWS bit

That syntax is new for 12c. And it’s awesome. It’s much nicer than doing a WHERE ROWNUM < 11 or whatever. You can skip rows, read rows, etc.

Sorry I didn't make this more clear when I first posted this. Or maybe I wanted to you to try it and see this cool technology for yourself :) Or maybe I was lazy.

In my defense, we’ve been talking about this since 2013.

Setting Default Script Execution Directory in SQLcl

$
0
0

We have a script execution directory setting in SQL Developer…but what about our new SQLcl command line utility?

That was a question posed to me this morning.

My answer was..well, let me show you my answer.

Here's where I'm at, directory-wise as I get set to launch SQLcl

Here’s where I’m at, directory-wise as I get set to launch SQLcl

I'm in, and I go to execute my employees.sql script

I’m in, and I go to execute my employees.sql script

But wait, where is it getting the employees.sql script from exactly?

But wait, where is it getting the employees.sql script from exactly?

Oh yeah...what's in there?

Oh yeah…what’s in there?

┌─[16:31:49][wvu1999][MacBook-Air-Smith]:~/sqlclNEW$
└─>cat login.sql
SET sqlprompt "_user '@' _connect_identifier >"
SET sqlformat ansiconsole
cd /Users/wvu1999/scripts
┌─[16:31:57][wvu1999][MacBook-Air-Smith]:~/sqlclNEW$
└─>

Now you can see why:

  • My prompt is what it is
  • My output is formatted nicely
  • My script is able to be found

In Case This is All New to You…

SQLcl is a new take on SQL*Plus brought to you by the SQL Developer team.

CD is a new command available. From the HELP…

Note we also support the /nolog option :)

Note we also support the /nolog option :)

SET SQLFORMAT allows to you predefine your output to JSON, CSV, HTML, INSERTS..and also to set a ANSICONSOLE for pretty coloring and nicer text spacing and formatting.

Updated SQLcl: nicer inline editing and column completion

$
0
0

We updated the Early Adopter offering of SQLcl today.

Go get it.

But first, I’m assuming you’ve heard of SQLcl? If not –

Read the slidedeck, watch the movie.

We’ve put in a ton of enhancements and even more bug fixes.

And Kris showed off a new feature today that mimic’s our SQL Developer grid preference for displaying NULL ‘values’…

But what I want to talk about are the insight feature and the inline editor.

SQLcl HAS AN EDITOR BUILT-IN!

Yes, you can still call the ‘edit’ command, and bring up Notepad or vi, both defaults for Windows and *NIX.

Or you can set it to ‘inline’ and it will just launch the same editor you see when you try to arrow through the buffer of a statement you’re currently typing or have pasted in.

Some HELP might be in order at this point:

Note the DEFINE bit.

Note the DEFINE bit.

So in my login.sql, I have this:

SET sqlprompt "_user '@' _connect_identifier >"
SET sqlformat ansiconsole
define _EDITOR=inline
SET pagesize 25

Also, did you notice the bit about the Ctrl key sequences while editing in the inline editor?

Do you remember PC games from the 80’s? Up was always W, down was always S, and so on. Well that works now too. And at any time you want to just execute what you have in the editor, you have a hotkey for that too.

Let’s see a quick demo.

It's much more fun to DO vs WATCH - so get the EA and start coding!

It’s much more fun to DO vs WATCH – so get the EA and start coding!

Expect lots and lots and lots of DEMO and some free stickers at KScope15 next week from Kris and I.

SQLcl: Using the new CTAS Command

$
0
0

How often do you need to build a new table to test something out?

How often have you typed CREATE TABLE AS SELECT…

If the answer to both of those question is ‘quite a bit Jeff!,’ then continue reading.

In SQLcl, we have built a new command simply called ‘CTAS.’

So let’s try it out.

What tables do I have to work with?

'tables' is a shorthand query we ship as a ALIAS example

‘tables’ is a shorthand query we ship as a ALIAS example

I’m lazy, so instead of typing ‘select table_name from user_tables’ I just types ‘tables’ and execute that.

It’s a burned-in sample of one of our ALIASes. With the ALIAS command you can save your own statements for re-use. Anyways, I want a copy of the EMPLOYEES table.

Running CTAS

CTAS existing_table new_table

So nothing has actually happened yet...

So nothing has actually happened yet…

So nothing has been executed, but what have we done really?

Well, we generated the DDL for the EMPLOYEES table, substituted the new table name PEEPS in instead, added the ‘as select * from EMPLOYEES’ to it, and threw THAT into the command buffer.

So, when I hit edit, we’ll launch the default editor (I have mine set to the inline editor in SQLcl, or you could use Notepad or vi or whatever)

Now I can make any changes I want or need.

Now I can make any changes I want or need.

make edits, change column name, change query, whatever - ctrl+R to execute

make edits, change column name, change query, whatever – ctrl+R to execute

I now have my new table. The more complicated your base table is, the more typing this will save you. Imagine partitions…

The SQL*Plus Stuff You Like and Love Lives On in SQLcl

$
0
0

When demonstrating SQLcl, I get the feeling that half of the audience is filled with dread.

Yes, they love everything that I’m showing them.

But deep, deep down they are scared that the things they personally liked in SQL*Plus are going away.

I’m here today to alleviate those concerns.

Instead of asking you to just take my word for it, I’ll show you.

Now of course you COULD just download it yourself and have a go, but folks are busy, and I understand.

The CHANGE Command

I just always knew it as ‘c’ as in C/OLD/NEW. It’s a bit more complicated than that [Docs], but here goes.

You can now also set your editor to SQLcl's inline editor and just arrow around your buffer and change stuff as you please...

You can now also set your editor to SQLcl’s inline editor and just arrow around your buffer and change stuff as you please…

& and &&

I know that looks funny, but you know what I mean, and…

Prompts for value each time...

Prompts for value each time…

Reuses value from query to query

Reuses value from query to query

Your Prompt

The PROMPT and pretty much all of the other program specific settings can still be managed with the SET command.

Like this one…

SET SQLPROMPT “_USER’@’_CONNECT_IDENTIFIER _DATE> ”

You're seen Kris' beer emoji prompts, yes?

You’re seen Kris’ beer emoji prompts, yes?

A Side-Bar On Prompts

I’ve been chided by my boss to show the ‘cool’ PROMPT.

Since we’re a Java application, Unicode support is a given.

So, if your OS supports Unicode character display in your terminal window, then you can do cool things like this:

Do you even SQLDev?

Do you even SQLDev?

You can find a lot of the unicode emoji’s here.

Someone who has Windows 10, let me know if their CMD window has gotten any better. In Windows 7 I was unable to get this to ‘work’ in the default terminal or even a newer one like ConEmu64.

SET SQLPROMPT “_USER’@’_CONNECT_IDENTIFIER 🍺 > ” #FTW

Back to SET Commands…

A simple ‘SHOW ALL’ does just that. But, if you say HELP SHOW, you will see all of the things we can show.

Show me yours, and...

Show me yours, and…

Other Things

Yes, you can still use a LOGIN or GLOGIN script. Yes, you can insist on using DESC even though INFO is waaaaay better.

Our intent was not to break anything SQL*Plus offered, but to extend it with all the new stuff you’ve been seeing us add over the past year.

Still don’t believe me? That’s probably good, better to trust but verify.

If you have a question or if you are curious about a specific SQL*Plus ‘thing’ – drop me a note in the comments and I’ll reply as best I can.

CYGWIN and SQLcl

$
0
0

For those Windows users out there who want both a BASH shell AND a really cool command line interface to Oracle Database – I have good news!

We updated SQLcl yesterday to include support for CYGWIN.

I have Cygwin64 and Windows 7.

it's a UNIX system! #JurassicParkJoke

it’s a UNIX system! #JurassicParkJoke

We also added a new command, SHOW TNS.

This will help you figure out how and where we’re finding your TNSNAMES* files.

SQL> show tns
 
TNS Lookup locations
--------------------
1.  USER Home dir
    C:\Users\jdsmith
2.  TNS_ADMIN
    D:\
 
Location used:
-------------
        C:\Users\jdsmith
 
Available TNS Entries
---------------------
DevDay11
DevDay12CDB
DevDay12PDB
SQL>

So we’ll look in your home directory, your TNS_ADMIN space, and your $ORACLE_HOME\network\admin space..and I think we peak into your registry as well…anyways, you’ll be able to troublehshoot now why you’re entry isn’t coming up.

You can also run a TNSPING on your TNS entry as well.

If you think this is cool, then it’s really not even the tip of the iceberg. Kris talks about yesterday’s BIG news here – you can now do client-side javascript scripting in SQLcl. Really opens up all what you can do with the tool…example, loading a BLOB from a file

script load blog with javascript sqlcl oracle


SET PAUSE ON

$
0
0

This has been around for a loooooong time.

But after a short chat with @oraclebase AKA Tim Hall yesterday, I thought I’d make sure we’re doing things right in the SQLDev tooling.

Tim uses it to make very nice, short, and sweet video demonstrations on his YouTube Channel. I highly recommend it. Anyways, back to PAUSE.

SET PAUSE ON [DOCS] in sql*plus allows a script to ‘pause’ until you hit ‘ENTER’ for it to continue.

We support this in SQLcl and SQL Developer now.

Nothing fancy, but it can be good for demo's or showing something to someone who can't read at the speed of light.

Nothing fancy, but it can be good for demo’s or showing something to someone who can’t read at the speed of light.

And in SQL Developer too.

Works best here if the lines don't wrap...not sure how useful it is in SQL Developer, but it's there.

Works best here if the lines don’t wrap…not sure how useful it is in SQL Developer, but it’s there.

SET PAUSE text works too!

SET PAUSE AreWeThereYet?

Don't make me turn this car around!

Don’t make me turn this car around!

The text is in the dialog/popup dialog...

The text is in the dialog/popup dialog…

Keyboard Shortcuts Cheat Sheet

$
0
0

Remember back when Corel first released WordPerfect? Remember how it had like a bazillion keyboard shortcuts, and you needed help remembering them all?

No? You probably also don’t remember a world sans e-mail and smart phones either. Oh well.

Anyways, we have lots of keyboard shortcuts in SQL Developer and a few in SQLcl.

You might need help remembering them.

Cue the ‘nerd stick.’

Or at least that’s what I’ve always called these.

I know, I know, I forgot your FAVORITE ONE. But, you already know your favorites, yes?

I know, I know, I forgot your FAVORITE ONE. But, you already know your favorites, yes?

Maybe I’ll turn this into a sticker or something more tangible (click here for a PDF version)….

Also, I talk about shortcuts in general here.

Have a Mac?

Because of the weird relationship Apple has with the Function keys on their keyboards, I’m not sure how many Mac users LIVE on their keyboards like Windows users do.

Out of the box, many of the keyboard shortcuts are less than ideal. I did take a few moments to publish a Mac version of the keyboard shortcuts ‘cheat sheet’ though. And remember, you can always change these up to meet your needs.

For the 5-6% of our users out there who use Macs :)

For the 5-6% of our users out there who use Macs :)

Object Search in SQLcl?

$
0
0

I’m always looking for things. I love the ALT+G trick in SQL Developer.

But what about the command-line?

One of the really nice things about SQLcl is that if you can’t do what you want with the available commands, you can just build your own. That’s especially true now that we have JavaScript support.

But this is just plain, straight up SQL.

To build your own command, use ‘ALIAS’.

SQL> alias fuzzy=SELECT owner, object_name, object_type FROM dba_objects
WHERE object_name LIKE :name
ORDER BY 1,2,3
fetch FIRST 10 ROWS ONLY;

You can probably guess what this does.

You pass the binds in in the same order they appear in your query.

You pass the binds in in the same order they appear in your query.

So, pretty easy, yeah?

And if you forget what your ALIAS is, just do, ALIAS LIST ALIAS_NAME.

Or do ALIAS LIST to see them all.

SQL> alias list
 
fuzzy
locks
SEARCH
sessions
TABLES
tables2

Or do HELP ALIAS to get a refresher.

SQL> help alias
 
ALIAS
------
 
alias [<name>=<SQL statement>;| LOAD [<filename>]|SAVE [<filename>] | LIST [NAME] | DROP ]
 
Alias IS a command which allows you TO save a SQL, plsql OR sqlplus script AND assign it a shortcut command.
        "alias" - print a list OF aliases
        "alias list <aliasName>" - list the contents OF the alias
        "alias <aliasName>=select :one from dual;" - Simple alias command
        Define an alias simply BY USING the alias keyword followed BY a single identifier
        name followed BY an '='. Anything after the '=' will be used AS the alias contents.
        FOR example, IF it IS SQL, it will be TERMINATED BY a ';'. IF it IS PLSQL, it will
        be TERMINATED BY a '/'
 
Examples:
--------
1. SQL Example WITH Binds
 
        SQL> alias fred=SELECT :one FROM dual;
        IN this example, a bind variable can be SET up IN the alias.
        Running the alias IS done LIKE this below WITH any parameters
        TO the alias being bound TO a bind variable BY SQLcl
 
        SQL> fred 1
        Command=fred
        :ONE
        ----
        >
 
2. PL/SQL example
        SQL> alias db= BEGIN dbms_output.put_line('hi'); END;
        >  /
        Here the block OF PLSQL IS TERMINATED BY the '/' ON a separate
        line at which point it IS accepted AS a NEW alias.
 
        SQL> db
        Command=db
        PL/SQL PROCEDURE successfully completed.
        hi
 
Summary
-------
        alias ..=.. IS TERMINATED BY ';'
        alias ..=BEGIN OR ..=DECLARE IS TERMINATED BY a / ON a newline
        alias ON its own gives a list OF existing aliases.
SQL>

We ship with a very few simple ones out of the box, but I’m hoping the clever folks out there will come up with some real humdingers.

And about SQL Developer…

Our script engine in SQLcl and SQL Developer are essentially the same. And actually, they are exactly the same. It’s the same code. Now, while it might not make sense to do things in SQL Developer that you do in SQLcl, you theoretically CAN.

an alternative to sql code templates perhaps

an alternative to sql code templates perhaps

While the alias command works, they’re not stored in SQLDev for use in the next application startup…

Click vs Type…Again.

$
0
0

This might sound preachy, but it’s mostly not intentional, mostly.

You might really enjoy the flexibility of the PL/SQL APIs the database provides for things like Resource management, the Scheduler, Data Pump. You might even have memorized the PL/SQL function/proc names and arguments required to create a job, or change up a resource.

But do you really want to spend that much time typing?

So.

While I can show DBAs, over and over again, how easy SQL Devleoper makes using this features, I’m never going to convince them to give up ‘control.’

But can you have your cake and eat it, too?

I say ‘yes.’

EVERY panel/wizard in SQL Developer will show you the SQL or PL/SQL generated to satisfy your request. Once you get that, send it to a worksheet or file. Then add/remove/change whatever you like. Then go run that in SQL*Plus or SQLcl.

Let us at least help get the ball rolling with your big anon PL/SQL block.

Let us at least help get the ball rolling with your big anon PL/SQL block.

And then when you’ve got your code all nice and ready, go run it wherever you want.

It won't hurt, I promise.

It won’t hurt, I promise.

Your Definitive Guide to SQL History

$
0
0

I went to link to this post earlier today, and was shocked to discover I hadn’t actually written it yet.

What’s the opposite of ‘bazinga!’ ?

SQL Developer stores every query AND script you execute in a worksheet.

A query being a single statement, and a script being one or more queries and/or anonymous blocks.

A query is stored as a single item.

A ‘script’ is stored as a single item.

By DEFAULT, we store the last 100 executed items.

When query 101 is executed, the least recently executed item will ‘age out’ of the list.

The Preference

You probably want to bump this up to several hundred, if not 1,000.

You probably want to bump this up to several hundred, if not 1,000.

We do NOT save queries which fail to run due to errors. This saves your precious history from being aged out by bogus queries.

Do NOT set your SQL History limit to ‘30,000’ and then complain that it takes SQLDev 10+ minutes to startup. #TrueStory. Each item is saved in a separate XML file. Each file is read into memory at startup time.

Your Query History is physically stored here – accessible to ALL of your SQL Developer local installs! So there is ONE SQL History stored on your computer, not one for each version of SQL Developer on your machine.

Upgrade SQLDev, your history will still be there.

It's 101 files, because there's a master index XML file that references the other 100 items (files.)

It’s 101 files, because there’s a master index XML file that references the other 100 items (files.)

Accessing the SQL History List

F8 or View > SQL History.

You get a panel.

Mouse hover over a script item, and you'll see that I'm not fibbing about entire scripts going into your history...

Mouse hover over a script item, and you’ll see that I’m not fibbing about entire scripts going into your history…

Items can be sorted and filtered. What’s shown on the panel is what will be available for recall, whether you use the mouse or keyboard.

Note that we store the last time executed, total times executed, and where you executed it.

So you can see it. How do you get it to the SQL Worksheet?

The default button will 'tack' the highlighted history item to wherever your cursor is in the Worksheet. The other button will CLOBBER the worksheet and you'll be left ONLY with your query from the history.

The default button will ‘tack’ the highlighted history item to wherever your cursor is in the Worksheet. The other button will CLOBBER the worksheet and you’ll be left ONLY with your query from the history.

That’s the BORING way to access the history.

The more useful way is via the keyboard. I don’t even open the SQL History panel most days. What I want is usually something I ran in the last few moments. If I have to dig deep, then F8 + Search is my new best friend.

Don't like, or even HATE, these keyboard shortcuts? Change 'em.

Don’t like, or even HATE, these keyboard shortcuts? Change ’em.

You can change the SQL History keyboard actions in the Preferences.

SQL History in SQLcl

So in the command line edition of SQL Developer, we also have a SQL History. Default is also set to 100 items – it’s not configurable, YET. It is also storing invalid statements…today.

We’ll release SQLcl with ability to set these behaviors.

Recall is similar via keyboard. Just up or down arrow at the prompt.

You can also see the entire list with ‘HISTORY’

Do ‘HISTORY #’ to put that item in the buffer to be executed.

Nothing to setup or configure via rlwrap, this works 'out of the box.'

Nothing to setup or configure via rlwrap, this works ‘out of the box.’

SQLcl and SQL Developer maintain SEPARATE histories. You won’t see queries you ran in SQLcl showing up in SQL Developer and vice versa.

SQLcl: Optimizing Your History Lists

$
0
0

Since SQLcl is a command line tool, it’s not super helpful to have a huge command history list. How do I mean? Well, in the SQL Developer GUI, we have a History panel. It allows for sorting, filtering, scrolling, etc. So you can go ‘crazy’ and set your History limit to 1000 if you want. But, in SQLcl, we limit the user to their last 100 commands.

Now there are many commands you’ll be running in SQLcl that you won’t necessarily want to be stored in the history. For example, do you want to reserve 1% of your history to remember how to clear the screen?

So in the latest drop, available today, you can now tell SQLcl NOT to store certain things.

Scroll down to the bottom of the SQL Developer downloads page to get to the 12MB SQLcl package.

But, by default, the history will store EVERYTHING. So you have to take extra step(s) to prevent things going into the history.

Blacklisted Commands

The developers know that there will be lots of questions as they had new features, above and beyond what SQL*Plus offers. So you’ll find lots of good stuff in the HELP.

give us a comma delimited list of commands you don't want to go into your history

give us a comma delimited list of commands you don’t want to go into your history

Ok, so I don’t want to see SET commands or where I go to clear the screen, and a couple of other things.

NEW items won’t go into the history if they start with these words.

NEW items won’t go into the history if they start with these words.

If you already have a SQL History, you’ll need to clear it first, and then going forward these items won’t go in. Or just let them age out…

HISTORY CLEAR — this will clear your history :)

Failures

Ok, now maybe you’re going to work on a query. And you know it’s not going to work for awhile. Or, maybe you’re like me and you rarely get the SQL just right on your first try. In that case you MAY not want to save the failures.

It's a toggle. Run it to switch the mode.

It’s a toggle. Run it to switch the mode.

So I’m going to disable bad SQL going into the history.

Remember, by default, we record EVERYTHING.

Remember, by default, we record EVERYTHING.

I don’t think I’ll run in this mode that often. If I do turn it on, it will be on a short term basis, and then I’ll probably turn it off.

Formatting Code in SQLcl

$
0
0

Ever get a SQL statement from someone desperate for help?

There’s 2 things these people do that drive me nuts:

  • they send a SCREENSHOT of their code
  • they send the Query as a single line of text

If I’m in the command line, it’s real easy to fix the 2nd problem.

Just use the FORMAT command.

Disclaimer #1: No one sent me this code, this was just the first thing I found in my history that was on a single line…

Disclaimer #2: Don’t send me screenshots of your code.

Oh, I forgot to qualify the schema name...

Oh, I forgot to qualify the schema name…

Short, simple, sweet.

Want leading commas? Cue that religious debate…but you can get that, if you want.

For 2016, we are cooking up some fun things for you folks that use the code formatter in SQLcl or SQL Developer – so stay tuned.

If you’re missing out on other new features – like if you are still using DESC over INFO – use the HELP command. We go out of our way to help you NOT miss the goodies.

We underline & bold the new commands now.

We underline & bold the new commands now.


More SET SQLFORMAT fun in SQLcl

$
0
0

DELIMITED text files are popular ways of passing data around.

CSV anyone? The C stands for ‘Comma’ – regardless of what your smug European friends may have told you 😉 #TonguePlantedFIRMLYInCheek

Anyways, in SQL Developer, when using the export dialog to get a DELIMITED export for your dataset, you can set the delimiter and the string enclosure for your columns.

Don't like commas as delimiters? Set your own.

Don’t like commas as delimiters? Set your own.

So in the command line interface AKA SQLcl:

The first argument defines the delimiter, the 2nd defines the left enclosure, and the 3rd defines the right enclosure.

The first argument defines the delimiter, the 2nd defines the left enclosure, and the 3rd defines the right enclosure.

So you could have BEER emoji separated values files…

Speaking of SET SQLFORMAT…

Back in October, we made a tweak to the ANSICONSOLE. It’s VERY configurable now in terms of how you want numbers displayed. Don’t miss this awesome post from @krisrice.

Get Help, Just Hit TAB

$
0
0

You’re at the command-line, you need to add a data file to your tablespace.

You get most of the way through it, and you forget what’s next, doh!

In SQLcl, you can just hit the TAB key, and we’ll help you with the next keyword.

So not only do we have tab-completion for object and column names, we also look up keywords from the syntax diagrams in the Oracle Docs.

Confused?

Here’s an animated GIF.

Use your imagination, I’m just trying different things.

When you see the word go from lowercase to UPPERCASE and completing, that’s where I’m hitting the TAB key.

Type, type, type, all day long. Type, type, type while I sing this song...

Type, type, type, all day long. Type, type, type while I sing this song…

Update 2/8/2016

The developer decided making you type the first letter was too much…you can invoke the help immediately. This should make the next OTN update/release.

Thanks, Vadim!

Thanks, Vadim!

Getting Your Plans via SQL_ID

$
0
0

So of course you can just run a query in the worksheet to get this. But, you need to know a few things. So why not make it easy on yourself and code it into SQL Developer as a report?

So that’s what I’ve done as an example:

Top Grid Data coming from V$SQL.

Top Grid Data coming from V$SQL.

So, if you KNOW your SQL_ID, you can click on the SQL_ID field in the column header, and paste the SQL_ID to filter on that text. The bottom grid auto-populates on the top row, so you won’t need to click on anything after that to read the plan.

Here’s the query for the top bits – note I’m hard-filtering out certain schemas:

SELECT EXECUTIONS,
       PARSING_SCHEMA_NAME WHO,
       SQL_ID,
       CHILD_NUMBER,
       SUBSTR(SQL_TEXT, 0, 55) || ' ...',
       FIRST_LOAD_TIME
FROM V$SQL
WHERE PARSING_SCHEMA_NAME NOT IN ('SYS', 'CTXSYS', 'XDB', 'APEX_050000', 'ORDS_METADATA') AND
UPPER(SUBSTR(SQL_TEXT, 0, 8)) NOT LIKE '%DECLARE%' AND
UPPER(SUBSTR(SQL_TEXT, 0, 8)) NOT LIKE '%BEGIN%'
ORDER BY executions DESC

Hot Tip: Use a fixed width font for the Code Editors so the plan text lines up nicely!

I created another child report to just show the query itself.

This is a DBMS_OUTPUT style report.

This is a DBMS_OUTPUT style report.

Here’s the code behind this report:

DECLARE
code CLOB;
 
BEGIN
SELECT regexp_replace(sql_text, '( ){2,}', '<br>') INTO code
FROM v$sqlarea
WHERE sql_id = :SQL_ID;
 
dbms_output.put_line('<FONT SIZE=12>');
dbms_output.put_line(code);
END;

Now Let’s Talk About SQLcl

I’m lazy. Just show me the plan for the last query I ran.

This is easy with DBMS_XPLAN.

But remember, I’m lazy.

So I aliased this as ‘plan.’

I just have to run 'plan' now.

I just have to run ‘plan’ now.

I did this by running, first:

SYS@orcl🍻🍺 >alias plan= SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR)

Or, if you KNOW the SQL_ID and CHILD_NUMBER…

You pass in the values in order that they appear in the aliased command.

You pass in the values in order that they appear in the aliased command.

SYS@orcl🍻🍺 >alias plan2=SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(:ID, :CHILD))
  2* /
SYS@orcl🍻🍺 >plan2 'b6ty4f8a3has5' 1
 
Command=plan2
 
PLAN_TABLE_OUTPUT                                                                                                                             
SQL_ID  b6ty4f8a3has5, child NUMBER 1                                                                                                         
-------------------------------------                                                                                                         
SELECT  signature,TYPE  FROM    all_identifiers  WHERE   line = :1                                                                            
AND :2 BETWEEN col AND col + LENGTH(name)      AND object_name = :3 AND                                                                       
owner = :4      AND name        = :5      AND object_type = :6                                                                                
 
Plan hash VALUE: 363803733                                                                                                                    
 
--------------------------------------------------------------------------------------------------------------------------------------------  
| Id  | Operation                        | Name       | ROWS  | Bytes | Cost (%CPU)| TIME     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |  
--------------------------------------------------------------------------------------------------------------------------------------------  
|   0 | SELECT STATEMENT                 |            |       |       |     1 (100)|          |       |       |        |      |            |  
|*  1 |  FILTER                          |            |       |       |            |          |       |       |        |      |            |  
|   2 |   PX COORDINATOR                 |            |       |       |            |          |       |       |        |      |            |  
|   3 |    PX SEND QC (RANDOM)           | :TQ10000   |     1 |   287 |     1 (100)| 00:00:01 |       |       |  Q1,00 | P->S | QC (RAND)  |  
 
PLAN_TABLE_OUTPUT                                                                                                                             
|   4 |     PX PARTITION LIST ALL        |            |     1 |   287 |     1 (100)| 00:00:01 |     1 |     2 |  Q1,00 | PCWC |            |  
|*  5 |      FIXED TABLE FULL            | X$COMVW$   |     1 |   287 |     1 (100)| 00:00:01 |       |       |  Q1,00 | PCWP |            |  
|   6 |   NESTED LOOPS SEMI              |            |     1 |    15 |     2   (0)| 00:00:01 |       |       |        |      |            |  
|*  7 |    FIXED TABLE FULL              | X$KZSRO    |     2 |    12 |     0   (0)|          |       |       |        |      |            |  
|*  8 |    INDEX RANGE SCAN              | I_SYSAUTH1 |     1 |     9 |     1   (0)| 00:00:01 |       |       |        |      |            |  
|   9 |   NESTED LOOPS SEMI              |            |     1 |    18 |     2   (0)| 00:00:01 |       |       |        |      |            |  
|* 10 |    FIXED TABLE FULL              | X$KZSRO    |     2 |    12 |     0   (0)|          |       |       |        |      |            |  
|* 11 |    INDEX RANGE SCAN              | I_OBJAUTH1 |     1 |    12 |     1   (0)| 00:00:01 |       |       |        |      |            |  
|  12 |   NESTED LOOPS SEMI              |            |     1 |    72 |     4   (0)| 00:00:01 |       |       |        |      |            |  
|  13 |    MERGE JOIN CARTESIAN          |            |     1 |    60 |     3   (0)| 00:00:01 |       |       |        |      |            |  
|  14 |     NESTED LOOPS                 |            |     1 |    54 |     3   (0)| 00:00:01 |       |       |        |      |            |  
|  15 |      TABLE ACCESS BY INDEX ROWID | USER$      |     1 |    17 |     1   (0)| 00:00:01 |       |       |        |      |            |  
|* 16 |       INDEX UNIQUE SCAN          | I_USER1    |     1 |       |     0   (0)|          |       |       |        |      |            |  
|* 17 |      INDEX RANGE SCAN            | I_OBJ2     |     1 |    37 |     2   (0)| 00:00:01 |       |       |        |      |            |  
|  18 |     BUFFER SORT                  |            |     2 |    12 |     1   (0)| 00:00:01 |       |       |        |      |            |  
 
PLAN_TABLE_OUTPUT                                                                                                                             
|* 19 |      FIXED TABLE FULL            | X$KZSRO    |     2 |    12 |     0   (0)|          |       |       |        |      |            |  
|* 20 |    INDEX RANGE SCAN              | I_OBJAUTH1 |   276 |  3312 |     1   (0)| 00:00:01 |       |       |        |      |            |  
|  21 |   NESTED LOOPS SEMI              |            |     1 |    53 |     4   (0)| 00:00:01 |       |       |        |      |            |  
|  22 |    MERGE JOIN CARTESIAN          |            |     1 |    41 |     3   (0)| 00:00:01 |       |       |        |      |            |  
|  23 |     NESTED LOOPS                 |            |     1 |    35 |     3   (0)| 00:00:01 |       |       |        |      |            |  
|  24 |      NESTED LOOPS                |            |     1 |    27 |     2   (0)| 00:00:01 |       |       |        |      |            |  
|  25 |       TABLE ACCESS BY INDEX ROWID| USER$      |     1 |    17 |     1   (0)| 00:00:01 |       |       |        |      |            |  
|* 26 |        INDEX UNIQUE SCAN         | I_USER1    |     1 |       |     0   (0)|          |       |       |        |      |            |  
|  27 |       TABLE ACCESS BY INDEX ROWID| TRIGGER$   |     1 |    10 |     1   (0)| 00:00:01 |       |       |        |      |            |  
|* 28 |        INDEX UNIQUE SCAN         | I_TRIGGER2 |     1 |       |     0   (0)|          |       |       |        |      |            |  
|* 29 |      INDEX RANGE SCAN            | I_OBJ1     |     1 |     8 |     1   (0)| 00:00:01 |       |       |        |      |            |  
|  30 |     BUFFER SORT                  |            |     2 |    12 |     2   (0)| 00:00:01 |       |       |        |      |            |  
|* 31 |      FIXED TABLE FULL            | X$KZSRO    |     2 |    12 |     0   (0)|          |       |       |        |      |            |  
|* 32 |    INDEX RANGE SCAN              | I_OBJAUTH1 |     1 |    12 |     1   (0)| 00:00:01 |       |       |        |      |            |  
--------------------------------------------------------------------------------------------------------------------------------------------  
 
PLAN_TABLE_OUTPUT                                                                                                                   
 
Predicate Information (IDENTIFIED BY operation id):                                                                                 
---------------------------------------------------                                                                                 
 
   1 - FILTER((INTERNAL_FUNCTION("OWNER") OR  IS NOT NULL OR (INTERNAL_FUNCTION("OBJECT_TYPE#") AND  IS NOT NULL) OR                
              (INTERNAL_FUNCTION("OBJECT_TYPE#") AND  IS NOT NULL) OR ("OBJECT_TYPE#"=12 AND  IS NOT NULL)))                        
   5 - FILTER(("LINE"=:1 AND "OBJECT_NAME"=:3 AND "OWNER"=:4 AND "NAME"=:5 AND "OBJECT_TYPE"=:6 AND "COL"<=:2 AND                   
              "COL"+LENGTH("NAME")>=:2))                                                                                            
   7 - FILTER(("CON_ID"=0 OR "CON_ID"=3))                                                                                           
   8 - access("GRANTEE#"="KZSROROL")                                                                                                
       FILTER(((INTERNAL_FUNCTION("PRIVILEGE#") AND (:B1=7 OR :B2=8 OR :B3=9)) OR (:B4=13 AND INTERNAL_FUNCTION("PRIVILEGE#")) OR   
              (:B5=12 AND INTERNAL_FUNCTION("PRIVILEGE#")) OR (:B6=11 AND INTERNAL_FUNCTION("PRIVILEGE#")) OR (:B7=14 AND           
              INTERNAL_FUNCTION("PRIVILEGE#")) OR (:B8=22 AND INTERNAL_FUNCTION("PRIVILEGE#"))))                                    
  10 - FILTER(("CON_ID"=0 OR "CON_ID"=3))                                                                                           
  11 - access("OBJ#"=OBJ_ID(:B1,:B2,:B3,:B4) AND "GRANTEE#"="KZSROROL")                                                             
 
PLAN_TABLE_OUTPUT                                                                                                         
       FILTER(("GRANTEE#"="KZSROROL" AND INTERNAL_FUNCTION("PRIVILEGE#")))                                                
  16 - access("U"."NAME"=:B1)                                                                                             
  17 - access("SPECOBJ"."OWNER#"="U"."USER#" AND "SPECOBJ"."NAME"=:B1 AND "SPECOBJ"."TYPE#"=DECODE(:B2,11,9,14,13,NULL))  
       FILTER("SPECOBJ"."TYPE#"=DECODE(:B1,11,9,14,13,NULL))                                                              
  19 - FILTER(("CON_ID"=0 OR "CON_ID"=3))                                                                                 
  20 - access("OA"."OBJ#"="SPECOBJ"."OBJ#" AND "OA"."GRANTEE#"="KZSROROL" AND "OA"."PRIVILEGE#"=26)                       
       FILTER(("OA"."PRIVILEGE#"=26 AND "OA"."GRANTEE#"="KZSROROL"))                                                      
  26 - access("U"."NAME"=:B1)                                                                                             
  28 - access("T"."OBJ#"=OBJ_ID(:B1,:B2,12,:B3))                                                                          
  29 - access("TABOBJ"."OBJ#"="T"."BASEOBJECT" AND "TABOBJ"."OWNER#"="U"."USER#")                                         
  31 - FILTER(("CON_ID"=0 OR "CON_ID"=3))                                                                                 
  32 - access("OA"."OBJ#"="TABOBJ"."OBJ#" AND "OA"."GRANTEE#"="KZSROROL" AND "OA"."PRIVILEGE#"=26)                        
       FILTER(("OA"."PRIVILEGE#"=26 AND "OA"."GRANTEE#"="KZSROROL"))                                                      
 
 
 
 74 ROWS selected

Summary: When It Hurts, BE LAZY.

Create a report. Alias a command.

SQLcl Updated: Bug Fixes

$
0
0

There’s an update available for SQLcl on OTN, go get it now.

We’re closing bugs left & right, and we’re super close to 100% SQL*Plus support now.

As an example, we now support SET PAGESIZE 0…which comes in handy apparently if you want to spool a file w/o a leading blank line as described here.

Ta-da...

Ta-da…

Keep testing, keep sharing your feedback, and thanks!

Keep testing, keep sharing your feedback, and thanks!

Why DESC When You Can INFO in Oracle SQLcl?

$
0
0

INFORMATION is a new command available in SQLcl, a command-line interface to Oracle Database.

HR@orcl🍻🍺 >help information
INFORMATION
--------
 
This command IS LIKE DESCRIBE but WITH more details about the objects requested.
 
INFO[RMATION] {[schema.]object[@connect_identifier]}
INFO+ will SHOW COLUMN statistics
 
HR@orcl🍻🍺 >

It’s available for tables and views, of course.

Here’s a table. Note that we show the primary key marked with a ‘*’ in the column list.

HR@orcl🍻🍺 >info hr.departments
TABLE: DEPARTMENTS 
	 LAST ANALYZED:2015-09-09 22:01:34.0 
	 ROWS         :27 
	 SAMPLE SIZE  :27 
	 INMEMORY     :DISABLED 
	 COMMENTS     :Departments TABLE that shows details OF departments WHERE employees
                       WORK. Contains 27 ROWS; REFERENCES WITH locations, employees, AND job_history TABLES. 
 
COLUMNS 
NAME              DATA TYPE             NULL  DEFAULT    COMMENTS
*DEPARTMENT_ID    NUMBER(4,0)           No                          PRIMARY KEY COLUMN OF departments TABLE.
 DEPARTMENT_NAME  VARCHAR2(30 BYTE)     No                          A NOT NULL COLUMN that shows name OF a department. Administration,
                                                                              Marketing, Purchasing, Human Resources, Shipping, IT, Executive, Public
                                                                              Relations, Sales, Finance, AND Accounting. 
 MANAGER_ID       NUMBER(6,0)           Yes                         Manager_id OF a department. FOREIGN KEY TO employee_id COLUMN OF employees TABLE. The manager_id COLUMN OF the employee TABLE REFERENCES this COLUMN.
 LOCATION_ID      NUMBER(4,0)           Yes                         Location id WHERE a department IS located. FOREIGN KEY TO location_id COLUMN OF locations TABLE.
 REVIEW           VARCHAR2(4000 BYTE)   Yes   '{"comments": []}'    
 
Indexes
INDEX_NAME           UNIQUENESS  STATUS  FUNCIDX_STATUS  COLUMNS        COLUMN_EXPRESSION  
HR.DEPT_ID_PK        UNIQUE      VALID                   DEPARTMENT_ID                     
HR.DEPT_LOCATION_IX  NONUNIQUE   VALID                   LOCATION_ID                       
 
 
REFERENCES
TABLE_NAME   CONSTRAINT_NAME  DELETE_RULE  STATUS   DEFERRABLE      VALIDATED  GENERATED  
EMPLOYEES    EMP_DEPT_FK      NO ACTION    ENABLED  NOT DEFERRABLE  VALIDATED  USER NAME  
JOB_HISTORY  JHIST_DEPT_FK    NO ACTION    ENABLED  NOT DEFERRABLE  VALIDATED  USER NAME

And here’s a VIEW.

HR@orcl🍻🍺 >info emp_details_view
COLUMNS 
NAME              DATA TYPE           NULL  DEFAULT    COMMENTS
 EMPLOYEE_ID      NUMBER(6,0)         No                   this IS a COLUMN comment ON a VIEW.
 JOB_ID           VARCHAR2(10 BYTE)   No                   
 MANAGER_ID       NUMBER(6,0)         Yes                  
 DEPARTMENT_ID    NUMBER(4,0)         Yes                  
 LOCATION_ID      NUMBER(4,0)         Yes                  
 COUNTRY_ID       CHAR(2 BYTE)        Yes                  
 FIRST_NAME       VARCHAR2(20 BYTE)   Yes                  
 LAST_NAME        VARCHAR2(25 BYTE)   No                   
 SALARY           NUMBER(8,2)         Yes                  
 COMMISSION_PCT   NUMBER(2,2)         Yes                  
 DEPARTMENT_NAME  VARCHAR2(30 BYTE)   No                   
 JOB_TITLE        VARCHAR2(35 BYTE)   No                   
 CITY             VARCHAR2(30 BYTE)   No                   
 STATE_PROVINCE   VARCHAR2(25 BYTE)   Yes                  
 COUNTRY_NAME     VARCHAR2(40 BYTE)   Yes                  
 REGION_NAME      VARCHAR2(25 BYTE)   Yes

You can get the statistics for a table instead of the column comments if you want. Use INFO+ for that.

Info, plus some stats.

Info, plus some stats.

Let’s look at other things you can ‘INFO,’ like PL/SQL.

A Procedure

HR@orcl🍻🍺 >info add_job_history
/*  PROCEDURE  HR.ADD_JOB_HISTORY  */
    HR.ADD_JOB_HISTORY(   P_EMP_ID          =>  p_IN_param0  /*   NUMBER(6)   */,
                          P_START_DATE      =>  p_IN_param1  /*   DATE   */,
                          P_END_DATE        =>  p_IN_param2  /*   DATE   */,
                          P_JOB_ID          =>  p_IN_param3  /*   VARCHAR2(10 BYTE)   */,
                          P_DEPARTMENT_ID   =>  p_IN_param4  /*   NUMBER(4)   */);
HR@orcl🍻🍺 >

DESC for a PL/SQL procedure is nearly identical. It will print a table of the arguments. But with the INFO you can quickly copy and paste that into a script so you can execute it.

Same for a function.

HR@orcl🍻🍺 >info lpb_get_rev_doctemp_ep01
/*  FUNCTION  HR.LPB_GET_REV_DOCTEMP_EP01  */
    /*   RETURN VARCHAR2   */
     v_ret := HR.LPB_GET_REV_DOCTEMP_EP01(   P_APPR_ID   =>  p_IN_param0  /*   NUMBER   */);
HR@orcl🍻🍺 >

And for packages…you can INFO a package.procedure or package.function.

Everyone knows DBMS_OUTPUT.PUT_LINE, yes?

What about UTL_FILE.FOPEN*?

HR@orcl🍻🍺 >info dbms_output.put_line
Package
 
/* Package SYS.DBMS_OUTPUT */
/*  PROCEDURE  SYS.DBMS_OUTPUT.PUT_LINE  */
    SYS.DBMS_OUTPUT.PUT_LINE(   A   =>  p_IN_param0  /*   VARCHAR2   */);
 
 
HR@orcl🍻🍺 >info utl_file.fopen
Package
 
/* Package SYS.UTL_FILE */
/*  FUNCTION  SYS.UTL_FILE.FOPEN  */
    /*   RETURN PL/SQL RECORD   */
     v_ret := SYS.UTL_FILE.FOPEN(   LOCATION       =>  p_IN_param0  /*   VARCHAR2   */,
                                    FILENAME       =>  p_IN_param1  /*   VARCHAR2   */,
                                    OPEN_MODE      =>  p_IN_param2  /*   VARCHAR2   */,
                                    MAX_LINESIZE   =>  p_IN_param3  /*   BINARY_INTEGER   */);
 
/*  FUNCTION  SYS.UTL_FILE.FOPEN_NCHAR  */
    /*   RETURN PL/SQL RECORD   */
     v_ret := SYS.UTL_FILE.FOPEN_NCHAR(   LOCATION       =>  p_IN_param0  /*   VARCHAR2   */,
                                          FILENAME       =>  p_IN_param1  /*   VARCHAR2   */,
                                          OPEN_MODE      =>  p_IN_param2  /*   VARCHAR2   */,
                                          MAX_LINESIZE   =>  p_IN_param3  /*   BINARY_INTEGER   */);
 
 
HR@orcl🍻🍺 >

Support for more schema or database object types may be forthcoming, so stay tuned.

Viewing all 123 articles
Browse latest View live