Show warning on missing column on VSSDT - sql-server-data-tools

On Visual Studio 2019 SSDT. Inside a procedure we have:
create table a (test1 varchar(50))
create table #b (test2 varchar(50))
select a.nop from a
select a.nop from a, #b b where a.test1 = b.test2
The first select gives a warning of columns missing, but the second one doesn't.
Is any configuration available to force a warning (or error) on the second select? The moment a temp table is present visual allows anything, even when the missing field has the "a."

Related

Data truncation warning without width change

I have a BINARY(2) DEFAULT NULL column in a MariaDB InnoDB table to store country code, but I would like to remove nullability (the value is always set), so I am trying to run the following query:
ALTER TABLE `table_name` MODIFY COLUMN `country_code` BINARY(2) NOT NULL;
However, I have the following error:
Error 1265: Data truncated for column 'country_code' at row 357
There are no rows with values that exceed 2 characters, checked with
SELECT MAX(LENGTH(`country_code`)) FROM `table_name`
Which returns 2.
In that case, what is the possible cause of data truncation, and how to workaround?

Selected non-aggregate values must be part of the associated group. SELECT Command Failed

I am using the below query and it gives error that "Selected non-aggregate values must be part of the associated group. SELECT Command Failed."
SELECT TOP 100 X_ISP_AFF_ADDR_SEQ, CAST(COUNT(*) AS BIGINT) AS COUNT_ROW FROM S_CONTACT WHERE X_ISP_AFF_ADDR_SEQ NOT LIKE '%[a-zA-Z]%';
I changed the above query as written below but the error still persists.
SELECT TOP 100 X_ISP_AFF_ADDR_SEQ, CAST(COUNT(X_ISP_AFF_ADDR_SEQ) AS BIGINT) AS COUNT_ROW FROM S_CONTACT WHERE X_ISP_AFF_ADDR_SEQ NOT LIKE '%[a-zA-Z]%';
You presumably are missing a GROUP BY clause here:
SELECT TOP 100
X_ISP_AFF_ADDR_SEQ,
CAST(COUNT(*) AS BIGINT) AS COUNT_ROW
FROM S_CONTACT
WHERE
X_ISP_AFF_ADDR_SEQ NOT LIKE '%[a-zA-Z]%'
GROUP BY
X_ISP_AFF_ADDR_SEQ;
The exact error you were seeing with your original query has to do with that selecting X_ISP_AFF_ADDR_SEQ instructs Teradata to return a value for each record in the table, whereas COUNT() returns a value over the entire table. It is not possible (in general) to mix aggregates and non aggregates in a select clause.

Oracle Select invalid identifier error from a table created with create as select statement

I'm using Oracle 11g and I created a table B using a create as select statement.
The creation was succeeded :
create table B as select * from A;
HOWEVER when a run a Select on specific columns of B I got an error ORA-00904 : "Mycolumn_C": invalid identifier.
BUT when I run a select * from B , it works fine !
The point is that "MyColum_C" is an alias in the select statement on table A , as follows :
Create table B as select code, name, useday as "Mycolum_C", validperiod as "Mycolum_D, enddate from A
For some reason, select statement on newly created table B of those columns that had aliases on table A, generates erro invalid identifier.
Examples of statements that fails :
Select Mycolum_C from B
Select Mycolum_D from B
What is going on here ?
Any help is very welcome !

How to replace occurrence only on the start of the string in Oracle SQL?

I have a source column and I want to search for string values starting with 05, 5 971971 and 97105 to be replaced by 9715. As showin in output table.
SOURCE OUTPUT
0514377920 971514377920
544233920 971544233920
971971511233920 971511233920
9710511233920 971511233920
I tried following which works for first case.
SELECT REGEXP_REPLACE ('0544377905', '^(\05*)', '9715')FROM dual;
But following is not working, for second case:
SELECT REGEXP_REPLACE ('544377905', '^(\5*)', '9715')FROM dual;
Something is wrong with my regular expression. As I am getting: ORA-12727: invalid back reference in regular expression.
You can provide your four patterns using alternation; that is, in parentheses with a vertical bar between them:
with t(source) as (
select '0514377920' from dual
union all select '544233920' from dual
union all select '971971511233920' from dual
union all select '9710511233920' from dual
)
SELECT source, REGEXP_REPLACE (source, '^(05|5|9719715|97105)', '9715') as output
FROM t;
SOURCE OUTPUT
--------------- --------------------
0514377920 971514377920
544233920 971544233920
971971511233920 971511233920
9710511233920 971511233920
Depending on your data and any other restrictions you have, you may be able to make it as simple as replacing the first part of any string that has a 5 in it, which works for your small sample:
SELECT source, REGEXP_REPLACE (source, '^.[^5]?5', '9715') as output
FROM t;
That matches zero or more characters that are not 5, followed by a 5. That may be too simplistic for your real situation though.

SUM totals by FOR ALL ENTRIES itab keys

I want to execute a SELECT query on a database table that has 6 key fields, let's assume they are keyA, keyB, ..., keyF.
As input parameters to my ABAP function module I do receive an internal table with exactly that structure of the key fields, each entry in that internal table therefore corresponds to one tuple in the database table.
Thus I simply need to select all tuples from the database table that correspond to the entries in my internal table.
Furthermore, I want to aggregate an amount column in that database table in exactly the same query.
In pseudo SQL the query would look as follows:
SELECT SUM(amount) FROM table WHERE (keyA, keyB, keyC, keyD, keyE, keyF) IN {internal table}.
However, this representation is not possible in ABAP OpenSQL.
Only one column (such as keyA) is allowed to state, not a composite key. Furthermore I can only use 'selection tables' (those with SIGN, OPTIOn, LOW, HIGH) after they keyword IN.
Using FOR ALL ENTRIES seems feasible, however in this case I cannot use SUM since aggregation is not allowed in the same query.
Any suggestions?
For selecting records for each entry of an internal table, normally the for all entries idiom in ABAP Open SQL is your friend. In your case, you have the additional requirement to aggregate a sum. Unfortunately, the result set of a SELECT statement that works with for all entries is not allowed to use aggregate functions. In my eyes, the best way in this case is to compute the sum from the result set in the ABAP layer. The following example works in my system (note in passing: using the new ABAP language features that came with 7.40, you could considerably shorten the whole code).
report zz_ztmp_test.
start-of-selection.
perform test.
* Database table ZTMP_TEST :
* ID - key field - type CHAR10
* VALUE - no key field - type INT4
* Content: 'A' 10, 'B' 20, 'C' 30, 'D' 40, 'E' 50
types: ty_entries type standard table of ztmp_test.
* ---
form test.
data: lv_sum type i,
lt_result type ty_entries,
lt_keys type ty_entries.
perform fill_keys changing lt_keys.
if lt_keys is not initial.
select * into table lt_result
from ztmp_test
for all entries in lt_keys
where id = lt_keys-id.
endif.
perform get_sum using lt_result
changing lv_sum.
write: / lv_sum.
endform.
form fill_keys changing ct_keys type ty_entries.
append :
'A' to ct_keys,
'C' to ct_keys,
'E' to ct_keys.
endform.
form get_sum using it_entries type ty_entries
changing value(ev_sum) type i.
field-symbols: <ls_test> type ztmp_test.
clear ev_sum.
loop at it_entries assigning <ls_test>.
add <ls_test>-value to ev_sum.
endloop.
endform.
I would use FOR ALL ENTRIES to fetch all the related rows, then LOOP round the resulting table and add up the relevant field into a total. If you have ABAP 740 or later, you can use REDUCE operator to avoid having to loop round the table manually:
DATA(total) = REDUCE i( INIT sum = 0
FOR wa IN itab NEXT sum = sum + wa-field ).
One possible approach is simultaneous summarizing inside SELECT loop using statement SELECT...ENDSELECT statement.
Sample with calculating all order lines/quantities for the plant:
TYPES: BEGIN OF ls_collect,
werks TYPE t001w-werks,
menge TYPE ekpo-menge,
END OF ls_collect.
DATA: lt_collect TYPE TABLE OF ls_collect.
SELECT werks UP TO 100 ROWS
FROM t001w
INTO TABLE #DATA(lt_werks).
SELECT werks, menge
FROM ekpo
INTO #DATA(order)
FOR ALL ENTRIES IN #lt_werks
WHERE werks = #lt_werks-werks.
COLLECT order INTO lt_collect.
ENDSELECT.
The sample has no business sense and placed here just for educational purpose.
Another more robust and modern approach is CTE (Common Table Expressions) available since ABAP 751 version. This technique is specially intended among others for total/subtotal tasks:
WITH
+plants AS (
SELECT werks UP TO 100 ROWS
FROM t011w ),
+orders_by_plant AS (
SELECT SUM( menge )
FROM ekpo AS e
INNER JOIN +plants AS m
ON e~werks = m~werks
GROUP BY werks )
SELECT werks, menge
FROM +orders_by_plant
INTO TABLE #DATA(lt_sums)
ORDER BY werks.
cl_demo_output=>display( lt_sums ).
The first table expression +material is your internal table, the second +orders_by_mat quantities totals selected by the above materials and the last query is the final output query.

Resources