+ All Categories
Home > Documents > Sybase SQL

Sybase SQL

Date post: 04-Apr-2018
Category:
Upload: ambikabk1
View: 263 times
Download: 3 times
Share this document with a friend

of 27

Transcript
  • 7/31/2019 Sybase SQL

    1/27

    Introduction

    Sybase SQL Server 11- Has a Single-Process, Multi-threaded Database Engine- Includes a query optimizer

    Standard SQL:* DDL (Data Definition language),* DML (Data Modification langiage),

    * DCL (Data Control Language)Transact-SQL = SQL + flow-control (if and while), local variables, etc..

    4 main verbs: select, insert, update, delete.

    But even before these words - here are some often used commands (working with Sybase:

    FUC - Frequently Used Commands

    isql -Sserver -Uuser -Ppassword1> use some_database1> select db_name()1> select @@servername1> select user_name()1> sp_helpdb1> sp_helpdb dbname1> sp_help1> sp_help tablename1> set rowcount 2 -- to limit number of rows1> set rowcount 0 -- remove rowcount limitation1> select * from sometable where 1=2 -- to see column names1> vi -- to edit command1>select name from sysobjects where type = "V"1> quit

    Here are useful help commands:select name from sysobjectswhere name like "sp_help%"

    SELECT

    select from select au_lname, au_fname from authorsselect title_id, type, price, price * .1 from titlesselect * from publishersstring concatenation:select au_lname + ", " + au_fname from authors

    name ouput columns yourself - column aliasselect title_id, type, price "original price", price * .1 discount from titlesselect "Full Author Name" = au_lname +", " + au_fname from authors

    remove duplicates withdistinct:select distinct type from titles

    select distinct city, state from authors(here distinct refers to a combination of city and state, so that each column by itself may have duplicate entries)

    filtering rows with whereselect from where select au_lname, au_fname from authors where state="CA"

  • 7/31/2019 Sybase SQL

    2/27

    equality and inequality operators: = , or != , > , >= , < , select type, title_id, price from titles where price * total_sales < advance(can be applied to string comparison - default sorting order is ASCII)

    logical OR andANDselect au_id, city, statefrom authorswhere state="CA" or city="Salt Lake City"

    between and Ranges of Data: between and

    select title_id, price from titles where price between $5 and $10equivalent toselect title_id, price from titles where price >= $5 and price = $5 and price

  • 7/31/2019 Sybase SQL

    3/27

    min( ) - lowest numeric or sorting string or earliest date,max( ) - highest numeric or sorting string or latest date,count( ) - returns the number of non-null expressions,count(*) - returns number of rows found

    select avg(price) from titleselect avg(price) "avg" from titles where type = "business"

    select avg(price) "avg", sum(price) "sum" from titleswhere type in ("business","mod_cook")

    counting rows withcount(*):select count(*) from authors where state="CA"

    agregates functions discard null values

    sub-agregates withgroup by:select type, avg(price) "avg", sum(price) "sum" from titleswhere type in ("_business", "mod_cook")group by type

    When two or more columns are included ingroup by statement, agregates are based on unique combinations of these

    columns:

    select type, pub_id, avg(price) "avg", sum(price) "sum" from titleswhere type in ("_business", "mod_cook")group by type, pub_id

    In order for aggregates to properly subtotal (or subaverage or subcount) by non-aggregate values, all non-aggregate columns in theselect list should be repeated in the group by clause (see color above).

    Filtering results withhaving:where - selects rows before averaging:select type, avg(price) from titles where price > $10 group by typehaving select rows from the result set:select type, avg(price) from titles where price > $10 group by type having avg(price) > $20

    Example: find duplicates of au_id:select au_id, count(*) from authorsgroup by au_idhaving count(*) > 1

    Worktable - a temporary table which is created before distinct, having or order by are applied.

    select type, avg(price) from titles where pub_id="1289"group by typehaving avg(price) > $15order by avg(price) desc

    JOIN

    JOIN Operations:join using common key (or join key):select title, pub_namefrom titles, publisherswhere titles.pub_id = publishers.pub_id

    select title, pub_namefrom titles t

    inner join publishers p on t.pub_id = p.pub_id

    select au_lname, au_fname, titlefrom authors a, titles t, titleauthor tawhere ta.title_id = t.title.idand a.au_id = ta.au_idand type="psychology"

  • 7/31/2019 Sybase SQL

    4/27

    select t.*, pub_namefrom titles t, publishers pwhere t.pub_id = p.pub_id

    Outer join: left (*=) or right (=*): select pub_name, title from publishers p, titles twhere p.pub_id *= t.pub_idand ...

    select pub_name, title from publishers pleft outer join titles t on p.pub_id = t.pub_id

    where ...

    This query retrieves all pub_names from publishers. For any row that doesn't join successfully with titles, the title column willcontain a null for that row in the output.

    Subqueries - to be used instead of a constant: select title from titleswhere pub_id =

    ( select pub_id from publishers where pub_name = "Algodata Infosystems")

    Subqueries withIN(orNOT IN) can return multiple rows:select pub_name from publishers

    where pub_id in(select pub_id from titles where type = "business")

    subquery can be rewritten as aJOIN:select pub_name from publishers p, titles t where p.pub_id = t.pub_id and type = "business"

    Subqueries with exists - the best way to eliminate duplicates:select pub_name from publishers pwhere exists

    (select * from titles t where p.pub_id = t.pub_id and type = "business")

    not exists andnot in :select pub_name from publishers pwhere not exists

    (select * from titles t where p.pub_id = t.pub_id and type = "business")

    Unfortunately the "not exists" construct runs very slowly.A better (much-much faster) way (in 12.5) is to use the new syntax:

    select pub_name from publishers pleft outer join titles t on p.pub_id = t.pub_id and t.type = "business"where t.pub_id is null

    This following syntax I don't like - create problems (char/varchar, nulls):

    select pub_name from publisherswhere pub_id not in

    (select pub_id from titles where type = "business")

    Subqueries with agregates in the where clauses:select type, price from titleswhere price < (select avg(price) from titles)

    union operations:select city, state from authorsunion

    select city, state from publishers

    (duplicates will be automatically removed from the result unless you use union all )

    Here is one more example:select 95 "year", month, sum(dollar_sales)

  • 7/31/2019 Sybase SQL

    5/27

    from salescurrentgroup by monthunionselect 94 "year", month, sum(dollar_sales)from salescurrentgroup by month

    order by year, month

    select into, insert, update, delete

    Usingselect into:creates a table on the fly instead of returning the the output to the user:select distinct typeinto type_lookupfrom titles

    Example: create an empty copy of an existing table:select * into new_salesdetailfrom salesdetailwhere 1 = 2

    Adding rows with insert:insert authors (au_id, au_lname, au_fname, phone)values ("123-45-6789","Jones","Mary","212-555-1212")

    Columns that are not specified will be set to their default valuesIf you don't specify column names at all (which is very bad practice and dangerous) - then you have to provide values for ALLcolumns an in the right order:

    insert publishersvalues ("1235","New World Printing","GA","Atlanta")

    inserting several rows with select:insert authors_archive (au_id, au_lname, au_fname, phone, city, state, zip)select au_id, au_lname, au_fname, phone, city, state, zip from authorswhere state="CA"

    modifying rows with update:update publishersset pub_name = "Joe's Press"where pub_id = "1234"

    Example: update based on a join:update titlesset full_name = isnull(u.full_name,'')

    from db1..titles tit, db2..users uwhere tit.kid *= u.kid

    Example: double all prices in the table:update titlesset price=price*2

    update several columns simultaneously:update contactsset address1 = "5 W. Main St.",

    address2 = "Apt.3D",state="CT",zip="03838"

    where contract_id = 17938

    remove rows with delete:delete titleswhere type = "business"

  • 7/31/2019 Sybase SQL

    6/27

    Clearing the table:delete title

    ortruncate table titles

    truncate is faster, but it doesn't log individual deletions - thus the ability to recover database is compromised.

    Datatypes

    Datatypes:Once you create a column of certain datatype - you can not change it without dropping and re-creating the table ????

    create table my_table (id int not nullvalue float not nulldescription varchar(30) null

    )

    Storing strings:char - fixed length strings (max length - 255)varchar - variable-length strings (max length - 255)

    nchar - multi-byte character stringsnvarchar - variable-length multi-byte char stringstext - for very large strings (up to 2 GB of text per row)

    Storing binary data:binary - for fixed-length binary stringsvarbinary - for variable-length binary stringsimage - for storing large binary strings (up to 2 GB of image data per row)

    insert b_table (id, bin_col) values (19, 0xa134c2ff)

    using timestamp:

    create table timestamp_example( id int not null,code char(3) not null,ts timestamp not null )

    insert timestamp_example (id, code) values (17, "AAA")

    The server uses the unique transaction-log-row id as a timestamp. You can not specify this value.

    Optimistic locking:using tsequal() function to check the locking

    Storing BLOBs (binary large objects) using text and image datatypes:create table texts (id numeric(5,0) identity,item int not null,textstring text null

    )

    using insert:

    insert texts (item, textstring) values (1, null)insert texts (item, textstring) values (2)insert texts (item, textstring) values (3, "some text")insert texts (item, textstring) values (4, "some very long text")

    insert statement will not insert more than 1,200 bytes.string concatenation on strings longer than 255 chars is illegal

  • 7/31/2019 Sybase SQL

    7/27

    using writetext and readtext:The idea is to get the pointer to the text chain and to write directly to this chain without modifying the underlying row.To do this you should start with a non-null popinter stored in the row itself.

    Here is how to retrieve the pointer for a row:select id, textptr(textstring) textptr,

    datalength(textstring) datalengthfrom texts

    to write a new textstring value to the 3rd row:declare @pageptr varbinary(16)

    select @pageptr = textptr(textstring)from textswhere id = 3

    writetext texts.textstring @pageptr "some very long string"

    to read 50 bytes starting from position 4000:declare @pageptr varbinary(16)select @pageptr = textptr(textstring)

    from textswhere id = 3

    readtext texts.textstring @pageptr 4000 50textstring

    Date/Time datatypes:datetime (3 millisecons, 8 bytes)smalldatetime (1 min, 4 bytes)

    create table date_example (id int not nulldateval datetime not null)

    insert date_example (id, dateval) values (19, "September 25, 1996 3:15PM")

    you can use other forms of format, for example: 4/15/99

    select * from date_table where date = "9/3/95"select * from date_table where date >= "9/3/95" and date < "9/4/95"

    timestamp - a binary, ticks of some sort, it is not datetime

    drop table #test

    create table #test (id numeric(18,0) identity,ts timestamp,dt datetime,sm smalldatetime

    )

    insert #test(dt,sm) values (getdate(), getdate())

    select * from #test

    datediff(dd,"15-Apr-2000","15-Apr-2001") - returns '365'

    where LastActivityDate > dateadd(yy,-2,getdate())where LastActivityDate > dateadd(dd, -90, getdate())

    Logical datatype: bit - can not be indexed and can not be null: create table bit_sample (id int not null, description varchar(30) null, active bit not null)

    Numeric datatypes:int - 4 bytes signedsmallint - 2 bytes signed

  • 7/31/2019 Sybase SQL

    8/27

    tinyint - unsigned byte (0..255)float - 8 bytesreal - 4 bytesnumeric(7,2) - you can indicate total number of digits and number of digits after decimal point. Can be used with identity(automatic counter)decimal - similar to numeric, but can't be used with identitymoney - 8 bytessmallmoney - 4 bytes (+/-214,748.3647)

    create table numeric_example (id numeric(8,0) identity,

    num_col numeric(7,2))

    insert dollar_table (id, dollars) values (95, $12345.93)

    =================================================================================create table table_name ( ...)drop table table_namesp_helpsp_help table_name

    object's full name:database_name.owner_name.object_name

    pubs.dbo.authors

    Columns can have following properties: Null, Not null, Identity

    Views and Temporary Tables

    -

    Views - logical way of looking at data (you can treat them as tables): create view author_name as

    select last = au_lname, first = au_fname from authors

    select * from author_namedrop view author_name

    * note: dropping a view doesn't change data* views - help security by limiting access to tables* views - help make queries simpler* views can contain aggregate functions and grouping, joins, other views and a distinct clause.* views CAN NOT include "select into" , a compute clause, a union clause, and "order by" clause.* You can insert into, update and delete from views (restriction: allowed to affect only one base table).* Ifview includes columns from several tables, you can't delete rows from view or update columns from more than 1 table in asingle update statement

    * You can not update, delete or insert into a view containing the distinct clause.

    sp_help - lists all objects (including tables and views)to get a list of just the views:select name from sysobjects where type = "V"

    to see a list of columns in a view:sp_help view_name

    Renaming objects (tables, views, columns.) using sp_rename:sp_rename old_name new_namesp_rename 'table_name.old_col_name' , 'new_col_name'

    Adding columns to a table usingalter:alter table tt add

    middle_name varchar(20) null,fax varchar(15) null

  • 7/31/2019 Sybase SQL

    9/27

    NOTE: You can only add columns with null values.NOTE: You can't remove columns using alter. You have to recreate the table and indexes and insert data again, for example:

    create table lev1 (c1 int not null,c2 int null)CREATE UNIQUE CLUSTERED INDEX lev1_idx ON lev1(c1)CREATE NONCLUSTERED INDEX lev1_qib_idx ON lev1(c1,c2)

    insert lev1 values (1,2)insert lev1 values (2,2)insert lev1 values (3,2)

    ------- add columns -----------------alter table lev1 add c3 int null, c4 int null------- remove columns -------------exec sp_rename 'lev1','lev1_tmp'-- sp_rename 'lev1_tmp.lev1_idx', 'lev1_tmp_idx'-- sp_rename 'lev1_tmp.lev1_qib_idx', 'lev1_tmp_qib_idx'

    create table lev1 (c1 int null, c2 int null)CREATE UNIQUE CLUSTERED INDEX lev1_idx ON lev1(c1)CREATE NONCLUSTERED INDEX lev1_qib_idx ON lev1(c1,c2)

    insert into lev1 select c1,c2 from lev1_tmp

    drop table lev1_tmp -- this will automatically drop indexes

    Temporary Tables - are real tables created in the tempdb database. They have '#' before table name. They exist only for theduration of a user session (or stored procedure) and only accessible to this session. These tables are not recoverable (in case of acrush).select au_lname, au_fname, title, pub_id

    into #titles_and_authorsfrom authors a, titleauthor ta, titles twhere a.au_id = ta.au_id and t.title_id = ta.title_id

    Creating permanent Temporary table in tempdb:select * into tempdb..titles from pubs2..titles

    Rules & Defaults

    -Rules:create rule order_quantity as

    @quantity between 100 and 150000

    create rule color_rule as@color in ('black', 'brown', 'red')

    create rule pub_id_rule as@pubid like ('99[0-9][0-9]')or @pubid in ('0736', '0877', '1389')

    create rule date_rule as@date >= getdate()

    drop rule key_rule

    Binding rule to a column:sp_bindrule rule_name, 'table.column_name'

    sp_unbindrule 'table.column_name'

    Defaults:create default country_default as 'USA'create default age_default as 16create default time_default as getdate( )

  • 7/31/2019 Sybase SQL

    10/27

    binding default to columns in a table: sp_binddefault default_name, 'table.column_name'sp_bindefault country_default, 'demographics.country'sp_unbindefault 'demographics.country'

    you can define default for a column when you create a table.later you can change it using later table:alter table items

    replace price default null

    alter table items

    replace item_code default "N/A"

    To list all rules and defaults in a database:select name from sysobjects where type in ("R", "D")

    To examine the rules and defaults bound to the column in a table:sp_help table_name

    sp_helptext object_name

    Creating User-defined Datatypes:sp_addtype ssn_type, 'char(9)', "not null"

    Indexes and Constraints

    -Indexes:2 types of indexes - clustered and nonclustered. Both are B-tree.Clustered - only one clustered index per table can exist (data is maintained in clustered index order).Nonclustered indexes - you can have 249 of them per table. They maintain pointers to rows (not data pages).An index can contain up to 16 columns, but toal index width

  • 7/31/2019 Sybase SQL

    11/27

    " "" "' '' '" ' "' " '

    'I don''t know' "I don't know" " Title ""The Title"" was on sale" ' Title "The Title" was on sale'

    math.functions: abs(), ceiling(), exp(), floor(), pi(), power(), rand(), round(), sign(), sqrt()date functions: getdate(), datename(), datepart(), datediff(), dateadd()

    convert - to convert data types:select "Advance = " + convert (char(12), advance) from titles

    (can also convert dates)

    system functions: host_id(), host_name(), suser_id(), suser_name(), user_id(), user_name(), user, show_role(), db_id(), db_name(),object_id(), object_name(), col_name(), col_length(), index_col(), valid_name(), datalength(), tsequal()

    compute, compute by:allows to include both detail and summary info in a single result set

    isnull - function tells to treat null values as zero or something else.

    Batches:several commands followed by 'go' command

    Comments: /* */ or *Local variables:

    declare @variable_name datatypedeclare @myname varchar(30), @type intselect @myname=12go

    note: name length is limited to 30 char (including @)

    Global variables - can not be defined by users.(examples: @@rowcount, @@error, @@trancount, @@transtate, ...)

    Message handling:print "this is a message"declare @msg varchar(30)select @msg = "Hello " + user_name()print @msg

    Error handling:raiserror 52345 'Row not found'

    if .. else:if (select ...)

    print "sometext"else

    print "some_other_text"while:

    while(select ...)begin

    update ...

    continuebreak

    endgoto:metka: select ......goto metka

    waitfor:waitfor time "22:00:00"while 1

  • 7/31/2019 Sybase SQL

    12/27

    return:to exit the batchset:set rowcount 100set statistics time onset nocount on...Cursors - allow custom processing for each row:declare leads_curs cursor forselect cust_id, ets-sale from leadsfor read only

    go

    open leads_curswhile () begin .. endclose leads_cursdeallocate leads_cursgo

    You can do also custom updating with cursors.In general you should avoid cursors - try to substitute them sith complex select statements (usually will run x10 faster)

    Triggers

    ***************-

    create trigger [owner.]trigger_nameon [owner.]table_name{for {insert, update, delete}as SQL_statements

    Or, using the if update clause:

    create trigger [owner.]trigger_nameon [owner.]table_namefor {insert, update}as[if update (column_name ) [{and | or} update (column_name)]...]

    SQL_statements[if update (column_name) [{and | or} update (column_name )]...

    SQL_statement ]...

    Example:

    create trigger titles_trigger

    on titlesfor insert

    asprint "title inserted"return***************-drop trigger trigger_name***************-create trigger cascade_del_trigger

    on publishersfor delete

    asif @@rowcount = 0 -- no rows deleted, exit trigger

    returndelete titles from titles t, deleted d where t.pub_id = d.pub_id

    if @@error != 0beginprint "Error occurred during deleting related titles"end

  • 7/31/2019 Sybase SQL

    13/27

    return***************-create trigger tr1 on ... for insert, update asdeclare @rows intselect @rows = @@rowcount...if (.. )

    ...***************-In triggers you CAN NOT do these:

    create, drop, alter table/database, grant, revoke, select into, truncate table, update statistics, reconfigure, load database/transaction,

    disk init/mirror/reinit/refit/remirror/unmirror***************-Triggers During transactions:...begin tran add_titlesinsert ...insert ...commit tran***************-rollback trigger - command to rollback the trigger

    Nested Triggers - 16 levels of nesting max ,

    Stored procedures

    Stored Procedures:* faster (precompiled in memory)* reduced network traffic* modular programming* restricted access to tables* reduced operator error* enforced consistency* automated complex or sensitive transactions

    ***************-create proc pub_titles as select .. from ... where ... return

    To execute a stored procedure:call by name if it is a first command in the batchor use "exec" (or "execute" command):

    exec proc_name

    To delete the procedure:drop proc proc_name

    To change the procedure:if exists (select * from sysobjects where name = "titles_for_a_pub" and type = "P" and uid=user_id())

    drop proc titles_for_a_pubgocreate proc titles_for_a_pub as ...

    To display the text of the procedure:sp_helptext proc_name

    passing parameters:create proc tt (@pub_name varchar(40)) asselect ...where ...return

    declare @my_pname varchar(40)select @my_pname ="Some text"exec tt @my_pname

    Default Parameter Values:create proc proc_name

    p_name datatype = default_value

  • 7/31/2019 Sybase SQL

    14/27

    , ....asSQL Statementsreturn ...

    ----- Output parameters:create proc tt (

    @par1 varchar(80) = null,@par2 int output)

    as-- some T-SQL statements go here

    return

    declare @myoutput intexec tt

    @par1 = 'sometext',@par2 = @myoutput output

    go

    ----- Returning procedure status:return some_int_value0 - no errors*1 .. -99 - detected errors (page 194 - list of error status codes)

    other values - whatever you like

    declare @staatus_var intexec @staatus_var = proc_name

    Note: A stored procedure may NOT: create views, defaults, rules, triggers or procedures, or issue the use statementNote: If stored procedure references a table, and the table was changed - you may have to drop procedure, change it and re-create it.When created, stored procedure is transformed into a cashed sequenced of SQL statements. If procedure has "with recompile" - itforces the optimizer to generate a new query plan for each execution.

    ----- Returning data from one SP into a caller-SP:---------------------------------------- transparent passing the result value

    -----------------------------------create proc test1 as select count(1) N from OEcreate proc test2 as exec test1exec test2---------------------------------------- catch the output value in the caller SP:-----------------------------------create proc test3(@a int, @b int output) as select @b = @a*@a

    create proc test4 asbegin

    declare @par_in int

    declare @par_out intdeclare @ret_status intselect @par_in = 3exec @ret_status = test3 @par_in, @par_out outputif not @ret_status=0 begin select @par_out = 0 endselect @par_outselect @par_out+1

    end

    exec test4---------------------------------------- transparent passing the result set-----------------------------------

    create proc test5 as select * from mytabcreate proc test6 as exec test5exec test6

    ---------------------------------------- handling errors, transactions-----------------------------------

  • 7/31/2019 Sybase SQL

    15/27

    create proc myspasbegin

    declare @tran_cnt intdeclare @errs intdeclare @rows intselect @tran_cnt = @@trancount

    if @tran_cnt = 0begin transaction mytran

    else

    save transaction mytran

    -- do something useful-- then check for errorsselect @errs = @@errorif (@errs != 0)begin

    rollback transaction sbl_upd_tickerreturn @errs

    end

    select @loc=loc, @idx=idx from mytab

    if not @@rowcount=1beginrollback transaction mytranraiserror 30200return 30200

    end

    if @tran_cnt = 0commit transaction mytran

    select @my_id = (@loc * 10000000) + @idxreturn 0

    end

    Objects referenced in a procedure:exec sp_depends proc_nameexec sp_depends table_name

    Transactions

    Transactions - several statements grouped together and either commited or rollbacked all together(all individual steps are recorded into a transaction log for recovery in case of a crash)begin tran

    save tranrollback trancommit transet chained

    @@tranchained 0 - chained mode is off, 1 - chained mode is on

    begin transactionupdate somethinginsert something

    if ...begin ... commit transaction end

    elsebegin ... rollback transaction end

    Note: transactions put locks on pages (2K blocks of data)

    savepoints inside transaction:save tran item999

  • 7/31/2019 Sybase SQL

    16/27

    ...rollback tran item999

    Nested Transactions:@@trancount

    stored procedure with a transaction inside

    create proc p1as

    declare @trncnt intselect @trncnt = @@trancount -- save valueif @trncnt = 0

    begin tran p1else

    save tran p1

    /* do some work here */

    if (@@transtate = 2) -- or other error conditionbeginrollback tran p1return 25 -- error code indicating rollback

    end

    /* some more processing if required */

    if @trncnt = 0commit tran p1

    return 0 -- success

    nesting transactions - batch with transaction calls a stored procedure with a transaction inside

    .....

    declare @status_val int, @trncnt intselect @trncnt = @@trancount -- save valueif @trncnt = 0

    begin tran t1else

    save tran t1

    /* do some work here */

    if (@@transtate = 2) -- or other error conditionbegin

    rollback tran t1return -- exit batchend

    execute @status_val = p1 -- call procedure with transaction from inside transaction - thus nesting transactions

    if @status_val = 25 -- if proc p1 performed rollbackbeginrollback tran t1returnend

    if @trncnt = 0commit tran t1 -- decrements @@trancount to 0

    return

    triggers may be part of a transaction:

  • 7/31/2019 Sybase SQL

    17/27

    begin tranupdate titles

    set price=$99where title_id = "BU1234"

    commit tran

    rollback transaction in a triggerrollback trigger

    Transation modes:

    - chained mode - This is ANSI standard. You are always in a transaction. You never have to issue BEGIN TRANs because it isissued implicitly as soon as you connect, and then as soon as you finish previous transaction. So as soon as you issue explicitCOMMIT TRAN or ROLLBACK TRAN - you will get into a new transaction. It looks strange - you only close transactions withcommit or rollback - and never have to open it, because it is always already opened for you.

    - unchained mode (default for Sybase) - Each individual statement is atomic. If you want to put several statements in onetransactions - you have to explicitly issue BEGIN TRAN and at the end do COMMIT or ROLLBACK.

    Stored procedures remember in which mode they were compiled - and will not run in a different mode - unless you define themwith "anymode".

    Getting info from sys. tables

    some examples using sys tables

    --------------------------------------------------------select name from sysobjectswhere sysstat & 7 = 3order by name--------------------------------------------------------select

    rowcnt(t2.doampg),(reserved_pgs(t2.id, t2.doampg) + reserved_pgs(t2.id,t2.ioampg)),(t3.low), data_pgs(t2.id, t2.doampg), data_pgs(t2.id,t2.ioampg),(

    (reserved_pgs(t2.id, t2.doampg) + reserved_pgs(t2.id,t2.ioampg)) -(data_pgs(t2.id, t2.doampg) + data_pgs(t2.id,t2.ioampg))

    )from sysobjects t1, sysindexes t2, master.dbo.spt_values t3where t2.id = object_id('myTableName')

    and t1.id = object_id('myTableName')and t3.number = 1 and t3.type = 'E'

    -------------------------------------------------------select t1.name, t2.name, t1.length, t1.status

    from syscolumns t1, systypes t2where t1.id = object_id('my_name')and t1.usertype *= t2.usertype--------------------------------------------------------select t1.indid, t1.namefrom sysindexes t1where t1.id = object_id('my_name')and t1.indid > 0 and t1.indid < 255--------------------------------------------------------select index_col('my_name', indid_buf, keyid_buf, ...)--------------------------------------------------------select t1.namefrom master.dbo.spt_values t1, sysindexes t2

    where t2.status & t1.number = t1.numberand t2.id = object_id('my_name')and t2.indid = my_some_indid_bufand t1.type = 'I'and t1.number = 2--------------------------------------------------------select t1.name

  • 7/31/2019 Sybase SQL

    18/27

    from syssegments t1, sysindexes t2where t1.segment = t2.segmentand t2.id = object_id('my_name')and t2.indid = my_some_indid_buf--------------------------------------------------------select replstat = convert(bit, (t1.sysstat & -32768))from sysobjects t1where t1.id = object_id('my_name')--------------------------------------------------------

    Stored procedure with a cursor

    if exists (select 1 from sysobjectswhere name = "myname")

    drop proc mynamego

    create proc mynameasbegin

    declare @my_id int

    declare @root_my_id intdeclare mycursor cursor for (select my_id from MT)open mycursorfetch mycursor into @my_idwhile ((@@sqlstatus = 0))begin

    exec @root_my_id = MT_get_root @my_idinsert into MT_root_map_tmp (my_id, root_my_id)values (@my_id, @root_my_id)fetch mycursor into @my_id

    endclose mycursordeallocate cursor mycursor

    endgo

    script to copy data between databases

    You can copy data between databases using migrate utility in DBArtisan.Or you can use this script (it accepts table name as a parameter):

    #!/bin/sh -v

    if [ $# != 1 ]then

    echo "Usage: $0 "exit 1

    fi

    table=$1

    PROD="-S SERV1 -U user1 -P pass1"DEV="-S SERV2 -U user2 -P pass2"

    bcp mydb..$table out $table.dat $PROD -n > /dev/null

    isql $DEV -w250

  • 7/31/2019 Sybase SQL

    19/27

    goEOF

    bcp mydb..$table in $table.dat $DEV -n > /dev/null

    isql $DEV -w250 {name};@ar = unpack('C*', $name);%hh = ();for(@ar) {if($_127){$hh{$_}++}}for(sort keys %hh){print"id : code $_ - $hh{$_} times\n"}

    }

  • 7/31/2019 Sybase SQL

    20/27

    declare @a varchar(30)

    select @a = "a b"select @a = str_replace(@a, char(32), rtrim(''))select @a-- the above returns 'ab' in Sybase 12.5.1 and later, but returns NULL in 12.5.0, which is a bug-- The alternative is to use a while loop:declare @ss varchar(10) select @ss="a b"while (charindex(" ",@ss) > 0) select @ss = substring(@ss, 1, charindex(" ",@ss)-1) + substring(@ss, charindex(" ",@ss)+1, 255)select @ss===========================

    Using 'union' to do logical operations in single statement without creating temporary tables:

    Let's say we have a table with 2 columns (a,b):

    create table #t (a int null, b int null)insert #t (a,b) values (-1,6)insert #t (a,b) values (0,5)insert #t (a,b) values (1,4)insert #t (a,b) values (2,3)insert #t (a,b) values (3,2)

    and we want to return max(a) or max(b) depending on which one is larger.Here is how this could be done

    select max(b) mm from #thaving max(b) > (select max(a) from #t)unionselect max(a) mm from #thaving max(b) > (select max(b) from #t)

    tune your SQL

    Query Tuning Optionsset forceplan on - forces SQL Server to join the tables in a query in the order in which they are listed in the from clause.set table count - allows you to specify the number of tables that are considered at once as joins are optimized.sp_cachestrategy - disables and reenables cache strategies and large I/O for individual objects.specify the index, cache strategy, or I/O size for a query (for example: select * from mytab (index mytab_idx) where ...)set prefetch - allows you to enable or disable large I/O for a session.

    Benchmarking your query by hand:set statistics time onset statistics IO on

    Help your optimizer to make sure it has correct information about your table and uses it for queries and stored procedures. This infomay me incorrect, for example, after bulk loads:

    update statistics tabnamesp_recompile tabname

    Examine the showplan of your query:set showplan ongoset noexec on

    go

    or for a stored procedureset showplan ongoset fmtonly on

    go

  • 7/31/2019 Sybase SQL

    21/27

  • 7/31/2019 Sybase SQL

    22/27

    Getting Info About Rows and Sizes of Tables

    select Table_Name=object_name(id),"Rows"=convert(int,sum(rowcnt(doampg))),"ReservedKB"=sum(reserved_pgs(id,doampg))*2+ sum(reserved_pgs(id,ioampg))*2,"Data"=sum(data_pgs(id,doampg))*2 ,"Index"=sum(data_pgs(id,ioampg))*2from sysindexeswhere id in (select id from sysobjects where type='U')group by object_name(id)

    Testing Outer Joins

    When chaining joins,>> , =>, are OK,but>= is not allowed (even on a different key)

    -- testing outer joinscreate table #t1 (c1 varchar(10) null, c2 varchar(10) null)create table #t2 (c1 varchar(10) null, c2 varchar(10) null)create table #t3 (c1 varchar(10) null, c2 varchar(10) null)go

    -- row.colinsert #t1 values('1.1','1.2')insert #t1 values('2.1','2.2')insert #t1 values('3.1','3.2')insert #t2 values('1.1','1.2')insert #t2 values('2.1','2.2')insert #t2 values('4.1','4.2')insert #t3 values('1.1','1.2')insert #t3 values('2.1','2.2')insert #t3 values('5.1','5.2')

    select t1.*, t2.* from #t1 t1, #t2 t2 where t1.c1 = t2.c1select t1.*, t2.* from #t1 t1, #t2 t2 where t1.c1 *= t2.c1

    -- t1 < t2 > t3select t1.*, t2.*, t3.* from #t1 t1, #t2 t2, #t3 t3 where t1.c1 =* t2.c1 and t2.c1 *= t3.c1

    -- t1 > t2 > t3select t1.*, t2.*, t3.* from #t1 t1, #t2 t2, #t3 t3 where t1.c1 *= t2.c1 and t2.c1 *= t3.c1

    -- t1 < t2 = t3select t1.*, t2.*, t3.* from #t1 t1, #t2 t2, #t3 t3 where t1.c1 =* t2.c1 and t2.c1 = t3.c1

    -- t1 > t2 < t3 - meaninglessselect t1.*, t2.*, t3.* from #t1 t1, #t2 t2, #t3 t3 where t1.c1 *= t2.c1 and t2.c1 =* t3.c1

    -- t1 > t2 = t3 - not allowedselect t1.*, t2.*, t3.* from #t1 t1, #t2 t2, #t3 t3 where t1.c1 *= t2.c1 and t2.c1 = t3.c1

    -- t1 > t2 = t3 - not allowed even on a different keyselect t1.*, t2.*, t3.* from #t1 t1, #t2 t2, #t3 t3 where t1.c1 *= t2.c1 and t2.c2 = t3.c2

    print, raiserror-===============================================Example of using print with formatting string:===============================================declare @a varchar(20)select @a = convert(varchar(20),getdate(),112)

    print @a

    declare @b varchar(20)select @b = 'I am b'print @b

  • 7/31/2019 Sybase SQL

    23/27

    print "MYMY %1! and %2! MYMY", @a, @b

    ===============================================Few words about raiserror===============================================raiserror is similar to print command, but it alsosets the @@error global variable to a int nubmer.Sybase has its own errors with numbers

  • 7/31/2019 Sybase SQL

    24/27

    if (@myflag != 1)returndeclare @mydate varchar(30)select @mydate=convert(varchar(30),getdate(),109)print "%1! === line ~ %2! === %3!", @mydate, @myline, @mystringend

    Example of reporting a duration of some process:

    declare @mysec datetimeselect @mysec = getdate()

    -- do something

    if(@mydebug=1)beginselect @ss = "FINISHED, total run time = " + convert(varchar(20),datediff(ss,@mysec,getdate())) + " seconds"exec myprint @mydebug,1012,@ssend

    Example populating a "suffix" table (chopping words from the beginning until nothing left). This table is used as an index table tospeed up search of words/phrases inside the string. It allows to use "starts with" logic ( ... where ss like 'xxx%' ), which uses index -thus it is fast.

    CREATE PROCEDURE dbo.ins_words (@words varchar(100) = null,@id varchar(32) = null,) asBEGIN

    -- clean the @wordsselect @words = upper(rtrim(ltrim(@words)))select @words = str_replace(@words, char(10), " ") -- \nselect @words = str_replace(@words, char(9), " ") -- \tselect @words = str_replace(@words, "|", " ") -- we do this to be able to bcpselect @words = str_replace(@words, "-", " ") -- dash is also a separator

    while (charindex(' ',@words)>0)select @words = str_replace(@words, " ", " ") -- remove double spaces

    -- we insert the whole string (even if it is empty - we still want to enter the id to make future updates easier)insert mytab (words, id) values (@words, @id_cas)if (rtrim(@words) = null)return

    declare @pos intselect @pos = charindex(' ', @words)while (@pos > 0) -- have to insert substring(s)begin

    insert mytab (words,id) values (substring(@words,(@pos+1),200), @id)select @words = substring(@words,(@pos+1),200)select @pos = charindex(' ', @words)end

    END

    Update with variables technique:

    -- Example 1declare @mycount int select @mycount=0update jds_contact set @mycount = @mycount + 1select @mycount

    -- We can do more interesting things - for example, concatenate values for the same id.let's say we have 2 columns (id, name).first, we create a temporary work table with 4 columns:(id, id_prev, name, names)

  • 7/31/2019 Sybase SQL

    25/27

    This table should have only fixed-width fields (no varchar). This is necessary so that the table will be written to the same place -thus preserving th order of rows.Next we insert data into this table (order by id).Next we update the id_prev field:

    select @prev = 0update #work set id_prev = @prev, @prev = id

    Next we do concatenation:

    select @ss=""update #workset names = case when id != id_prev then rtrim(name) else rtrim(@names)+', '+rtrim(name) end,@ss = case when id != id_prev then rtrim(name) else rtrim(@names)+', '+rtrim(name) end

    Finaly select the result:

    select id, max(names) from #work

    Example of batch inserting using id:

    declare @myrowcount int select @myrowcount=1declare @min_id int, @max_id int, @base_id int

    select @min_id = min(id), @max_id = max(id) from sourceselect @base_id = @min_id - 1select * into #batch from dest where 1=2

    set rowcount 5000

    while (@myrowcount > 0)

    begindelete #batch

    insert #batchselect * from source twhere t.id > @base_idorder by t.id

    select @myrowcount = @@rowcount

    select @base_id = max(id) from #batch

    if (@myrowcount > 0)begininsert dest select * from #batch

    print "inserted = %1! (max = %2!)", @base_id, @max_idend

    end

    set rowcount 0

    Reducing the locking problem.

    Read - put shared lock, update or insert - exclusive lock.

    Table locks may be a result of lock promotion, but more often they happen because of your SQL / indexes. Normally table read putsa shared lock. But if you have an UPDATE or a DELETE with a WHERE clause which has a table scan - you will get an exclusivetable lock without any lock promotion, regardless of locking scheme.

    Switching to row level locking (DATAROWS locking scheme) may not solve your problem and is very expensive: your data takesup more space, UPDATES start causing a lot more fragmentation, and you need A LOT more locks. Lock promotion works bynumber of locks used, and since DATAROWS uses considerably more locks, you'll hit promotion threshold much sooner. Also if

  • 7/31/2019 Sybase SQL

    26/27

    you run out of locksyou will also get a promotion to a table lock. Also, if you are committing more rows at a time than the HWM(high lock promotion threshold)then you will still get lock promotion even with datarows locking scheme.

    There are 3 locking schemes:- ALLPAGES (data and indexes)- DATAPAGES (only data)- DATAROWS (only data, row-level locking)

    Use sp_lock and sp_objectstats to see if multiple connections/users attempt locks on rows on the same page. Use sp_sysmon todetect lock promotion.

    Lock promotion thresholds :LWM = 200 - never attempt a promotion below 200 locksHWM = 200 - always attempt promotion once 200 are reached(HLW - High WaterMark, LWM - Low WaterMark)Number of locks = 35,000

    Note: Switching to DATAROWS might help your blocking, but maybe the problem isn't that people are trying to read the samerow, or even different rows on the same page. It might be that they're blocking on data vs index access. DATAPAGES is a goodfirst step to try since it eliminates index locking and usually this is all you need. It has most of the benefits of DATAROWS withoutthe extreme overhead. It's always a good idea to try DATAPAGES first.

    Also, the solution to avoid table locks may be simply to increase the lock promotion thresholds.

    Note: changing from ALLPAGES to DATAPAGES or DATAROWS is an expensive operation. Switching between DATAPAGESand DATAROWS is very easy and fast.

    Note: if a WHERE clause has local variablesoptimizer will not use index, thus causing a table scan.

    Example:Modifying locking scheme:

    alter table authors lock datarows

    Isolation Level

    You can change isolation level using a command like this:

    set transaction isolation level 0

    The value is stored in variable @@isolation

    Possible values:0 - read uncommitted changes to data (allow dirty reads).1 - read committed only (default)2 - repeatable read - The transaction can repeat the same query, and no rows that have been read by the transaction will have

    been updated or deleted.3 - serializable read - The transaction can repeat the same query, and receive exactly the same results. No rows can be inserted

    that would appear in the result set.

    You can override the isolation level by adding a hint to the end of SQL statement:

    with holdlock - force level 3with noholdlock - force level 1

    AutoCommit

    set autocommit - the client-side commant to set autocommit on | off | 0 | 1 - turns autocommit on or off.

    Duplicates

    ignore_dup_key - hint to skip duplicate keys while doing insert or update. Note - you cannot create a unique index on a columnthat includes duplicate values or more than one null value, whether or not ignore_dup_key is set. If you attempt to do so, AdaptiveServer prints an error message that displays the first of the duplicate values. You must eliminate duplicates before AdaptiveServer can create a unique index on the column.

  • 7/31/2019 Sybase SQL

    27/27

    ignore_dup_row - allows you to create a new, nonunique clustered index on a table that includes duplicate rows. ignore_dup_rowdeletes the duplicate rows from the table, and cancels any insert or update that would create a duplicate row, but does not rollback the entire transaction.

    Example: to delete duplicate rows:create index index_name on table_name with ignore_dup_row

    allow_dup_row - allows you to create a nonunique clustered index on a table that includes duplicate rows, and allows you toduplicate rows with update and insert statements.

    tempdb, transaction log,

    You may have many databases on the same server. But until ver. 12.* there was only 1 tempdb database. This was creatingproblems, as many sessions were competing for it. Starting with ver. 12 you may have several database - thus distributing the load.

    Usuallythe size of tempdb is ~2 GBytes, however I've seen it as big as 12.5 GBytes - and completely buffered (mapped to memory).

    When you have large transactions - you may want to increase the sizes of both tempdb and transaction log. But if you havereplication - you want to limit the size of transactions to ~ 3,000 rows.

    Checkpoint event

    Approximately once a minute, the checkpoint task checks each database on the server to see how many records have been added tothe transaction log since the last checkpoint. If the server estimates that the time required to recover these transactions is greaterthan the databases recovery interval, Adaptive Server issues a checkpoint. The modified pages are written from cache onto thedatabase devices, and the checkpoint event is recorded in the transaction log. Then, the checkpoint task sleeps for another minute.To see the checkpoint task, execute sp_who. The checkpoint task is usually displayed as CHECKPOINT SLEEP in the cmd

    column.

    Working with big tables

    don't create a clustered index, because when you will need to drop and create it - ASE will lock the whole table.use range partitions to load data (starting with ver 15), and use local indexes (index on a partition) instead of global indexes.


Recommended