With your permission I will add some useful links on the topic:

Using my simple example, when the method receive a name param or a age param to build the where clause. I really don't know how to solve it using query class.

Query FilterBy(
  Name As %String "",
  Age As %Integer ""As %SQLQuery(CONTAINID 1SELECTMODE "RUNTIME") [ SqlName SP_Sample_Filter_BySqlProc ]
{
SELECT TOP IDNameAgeSSN FROM Sample.Person
WHERE 
(nvl(:Name,'')='' or Name %STARTSWITH :Name)
AND
(nvl(:Age,'')='' or Age >= :Age)
}

Run Examples:
select * from Sample.SP_Sample_Filter_By(,47)
select * from Sample.SP_Sample_Filter_By('',47)

select * from Sample.SP_Sample_Filter_By('s',47)

select * from Sample.SP_Sample_Filter_By('s')
select * from Sample.SP_Sample_Filter_By('s','')
SELECT 

NVL(order_description,'') ||

CASE WHEN NVL(dosage,'')='' OR NVL(dosage_unit,'')='' THEN ''
     ELSE ', ' || dosage || ' ' || dosage_unit || CASE WHEN NVL(dosage_form,'')='' THEN ''
                                                       ELSE ' ' || dosage_form
                                                  END || ''
END ||

CASE WHEN NVL(administration_route,'')='' THEN ''
     ELSE ', ' || administration_route
END ||

CASE WHEN NVL(frequency_description,'')='' THEN ''
     ELSE ', ' || CASE WHEN NVL(quantity,'')='' OR NVL(quantity_unit,'')='' THEN ''
                       ELSE quantity || ' ' || quantity_unit || ' '
                  END || frequency_description
END ||

IFNULL(start_date,'',', ' || 'Start Date: ' || CONVERT(SQL_DATE,start_date,101)) As MedicationOrder

FROM CWSOrderEntry.history_client_order
WHERE PATID='100068'
--AND FACILITY=?FACILITY
AND order_status_code='A'
AND order_type_category_code='P'

Symbols Used in Caché SQL

SELECT 
(CASE WHEN (order_description IS NULL OR (order_description='')) THEN '' ELSE (order_descriptionEND) ||
(CASE WHEN (dosage IS NULL OR dosage_unit IS NULL OR (dosage='') OR (dosage_unit='')) THEN ''
ELSE (', ' || dosage || ' ' || dosage_unit || (CASE WHEN (dosage_form IS NULL OR (dosage_form='')) THEN '' ELSE (' ' || dosage_formEND) || ''END) ||
(CASE WHEN (administration_route IS NULL OR (administration_route='')) THEN '' ELSE (', ' || administration_routeEND) ||
(CASE WHEN (frequency_description IS NULL OR (frequency_description='')) THEN '' ELSE (', ' || (CASE WHEN (quantity IS NULL OR quantity_unit IS NULL OR (quantity='') OR (quantity_unit='')) THEN '' ELSE (quantity || ' ' || quantity_unit || ' 'END) || frequency_descriptionEND) ||
(CASE WHEN start_date IS NULL THEN '' ELSE (', ' || 'Start Date: ' || CONVERT(SQL_DATE,start_date,101)) ENDAs MedicationOrder
FROM CWSOrderEntry.history_client_order
WHERE PATID='100068'
--AND FACILITY=?FACILITY
AND order_status_code='A'
AND order_type_category_code='P'

Try changing the font, it's possible that you just have "||" displayed as "!!".

Using the JSON Adaptor.

Simple example:

Class dc.test Extends (%RegisteredObject%JSON.Adaptor)
{

Property list As list Of %String;

/// d ##class(dc.test).test()
ClassMethod test()
{
  json={"list":["green","yellow,red","blue"]}
  
  t=..%New()
  t.%JSONImport(json)
  t.list.Count(),!,t.list.GetAt(2)
}

}

USER>##class(dc.test).test()
3
yellow,red

Also look at Using Document Database (DocDB).

Another option without %ZEN.Auxiliary:

Class dc.mylist Extends %ListOfDataTypes
{

Method SizeSet(newvalue As %IntegerAs %Status
{
  i%Size=newvalue
  q $$$OK
}

}


Class dc.test Abstract ]
{

/// d ##class(dc.test).test()
ClassMethod test()
{
  json=["green","yellow,red","blue"]
  t=##class(%Document.Object).CSON(json.%ToJSON())
  
  l=##class(dc.mylist).%New()
  
  l.Data=t."_data"
  zk l.Data
  s l.Size=t.Count()
  
  l.Count(),!,l.GetAt(2)
}

}

Defining and Using Stored Procedures

 
Source code
Result:
select * from dc.daterange('1-5-2019','5-25-2019')
dBegin dEnd
01-05-2019 01-31-2019
02-01-2019 02-28-2019
03-01-2019 03-31-2019
04-01-2019 04-30-2019
05-01-2019 05-25-2019

Defining Stored Procedures

 
Source code
Result:
select * from dc.numbers(107)
n
1
2
...
105
106
107

Through %ZEN.proxyObject is unlikely to work, since the q parameter cannot be disabled in this case

q - output numeric values unquoted even when they come from a non-numeric property

Use your own class, for example:

Class dc.test Extends %RegisteredObject
{

Property articlenumber As %String;

}
object ##class(dc.test).%New()
object.articlenumber "15049950"

##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.json,object,,,,"aelotw")

Output:

{
  "articlenumber":"15049950"
}

Conclusion: the quote will be removed from the documentation since it's no longer true.

Then besides this, in the documentation for %STARTSWITH need to add the note DEPRECATED and the recommendation "use LIKE 'XXX%'"

I also did an analysis for Caché 2018.1

Class del.t Extends %Persistent
{

Index ip On p;

Property As %VarString;

/// d ##class(del.t).Fill()
ClassMethod Fill(1000000)
{
  DISABLE^%NOJRN
  ^del.tD,^del.tI

  i=1:1:^del.tD(i)=$lb("","test"_i)
  ^del.tD=N
  ENABLE^%NOJRN

  ..%BuildIndices(,,,$$$NO)
  d $system.SQL.TuneTable($classname(),$$$YES)
  d $system.OBJ.Compile($classname(),"cu-d")
}
}

Although the plans are exactly the same in SMP the results of the metrics differ:

select count(*from del.where like 'test7%'
Row count: 1 Performance: 0.291 seconds 333340 global references 2000537 lines executed

select count(*from del.where %startswith 'test7'
Row count: 1 Performance: 0.215 seconds 333340 global references 1889349 lines executed

For the next two queries, the INT code matches:

&sql(select * from del.where like 'test7%')
&sql(select * from del.where %startswith 'test7')

But for these - is already different, so the metrics in SMP are different:

&sql(select * from del.where like :a)
&sql(select * from del.where %startswith :a)

In IRIS 2020.1, the work with embedded queries was changed, but I can't check it.