Just to make it as simple as possible as I am guessing you are new to Caché

ClassMethod Export(pGlobal, pFile)
    set file=##class(%File).%New(pFile)
    do file.Open("WN")
    set key=$order(^Global1(""))
    while key'="" {
        do file.WriteLine(^Global1key))
        set key=$order(^Global1(key))
    do file.%Save()

$ORDER() is a command that returns the next defined subscript value.  When you pass in "" it returns the first defined subscript value, 1 in your case.   After writing the value of ^Global1(n) to the file the final $ORDER() will return "" indicating there are no more defined subscript values.

for more details see our docs for $ORDER()


You did not overlook anything, we at ISC did.  The Enterprise Manager was never formally released or pulled shortly after release.  I have removed the reference to it from the WRC Distribution page.

I will ask Product Management to comment here about a future plans in this area.


The example you have above should have no problem handling the number of rows assuming the Business Logic is not building some huge thing in memory.

%Library.ResultSet has been replaced by %SQL.Statement.  We would expect %SQL.Statement to give you better performance then %Library.ResultSet.

To increase performance a little more Embedded SQL gives the best performance of all three options.  In older version of Cache the difference was pretty large.  In current version of Cache the difference is not that great.



Are you storing 64365 or 64365,23587?

If you are storing the first then the above answers are correct.  If you are storing the second then you will need to create your own Data Type class based on %Timestamp and write your own LogicalToStorage and StorageToLogical methods.

Cache has system functions that will convert $H to a readable format and back

USER>W $zdatetime($h)
03/23/2017 06:36:38

USER>W $ZDATETIMEH("03/23/2017 06:36:38")



Yes you can use any DML statements over ODBC to create new users and GRANT and REVOKE privs.

Create User:  http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

Grant :  http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

Revoke:  http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

We do not recommend making general use of the _SYSTEM username.  For a secure system you should either disable this account, or change the password and limit it's use.  Then create a new Cache User for each person connecting to the application.  You can first create a Role that has all the privs needed for a general user and then just GRANT that one Role to each User.

If you need more detailed examples on this you can contact InterSysetms Support and we will help you out.


There have been some conflicting info in the answers to this question so I am going to try and put all the correct info into one place.

Pluses for Process Private Globals:

  1) no size limit

  2) cleaned up by the system when the process exits

  3) explicit KILL will clean up PPG

  4) can be used in a class with Cache SQL Storage

Pluses for % Array:

  1) faster than PPG

  2)  cleaned up by the system when the process exits

  3) explicit KILL will clean up % array

  4) argumentless KILL will clean up % array

  5) Can be used in the NEW command

  6) can be used in a class with Cache SQL Storage

Negatives for Process Private Globals

  1) slower than % Arrays

Negatives for % Arrays:

  1) limited in size by the process memory

I hope this list is close to complete and accurate.



From a COS coding point of view you can get yesterday by setting Yesterday = $H-1

To get the number of days this month you can do the following:


of course all that can be squished into one line:  

w $H-$ZDATEH(($P($ZDATE($H,3),"-",1,2)_"-01"),3)

Looking at the DeepSee docs it looks like you can get some of the stuff using Now


year = birthd.[year].NOW


I am not an MDX guy so if this is the direction you want to go in you should talk to one of our DeepSee support people and I am sure they can tell you how to do this.

The default behavior for %String is case insensitive searching, so I would expect what Bachhar shows would be the same if he left off Collation = 'SQLUPPER".

It is possible to change the default collation for %String on a system, so maybe that is why you are seeing different results.  For example this command would make the default behavior %EXACT:

USER>w $$SetEnvironment^%apiOBJ("collation","%Library.String","EXACT")
USER>w $$GetEnvironment^%apiOBJ("collation","%Library.String",.current)
USER>w current

This is done on the namespace level


the format of an Object Id is $LISTBUILD(id,class) so when I delete a row from Sample.Person I get:

SAMPLES>zw oid

The Id is the first $List element:


The ORDER BY needs to go with the TOP, so your query should be

   (SELECT TOP 10 * FROM Sample.Person ORDER BY Name) 

then it does what you want.