據(jù)庫(kù)存儲(chǔ)過(guò)程實(shí)戰(zhàn):AMDP語(yǔ)法實(shí)例與TaoToken配置骨架)
1. AMDP 開(kāi)發(fā)環(huán)境搭建與 AI 輔助工具接入SAP AMDPABAP Managed Database Procedures是 ABAP 層管理 HANA 數(shù)據(jù)庫(kù)存儲(chǔ)過(guò)程的一套機(jī)制允許開(kāi)發(fā)者在 ADTABAP Development Tools里用 SQLScript 編寫(xiě)數(shù)據(jù)庫(kù)過(guò)程由 ABAP 類統(tǒng)一管理生命周期。它適合誰(shuí)適合已經(jīng)在做 SAP HANA 項(xiàng)目、需要在數(shù)據(jù)庫(kù)層直接跑應(yīng)用邏輯的 ABAP 開(kāi)發(fā)者尤其是那些發(fā)現(xiàn) CDS View 表達(dá)力不夠、又不想脫離 ABAP 傳輸體系去單獨(dú)維護(hù) HANA 存儲(chǔ)過(guò)程的人。我試過(guò)在純 SAP GUI 里翻 AMDP 源碼只能只讀瀏覽改不了。真正寫(xiě)代碼必須用 ADTEclipse 插件。而 ADT 本身沒(méi)有 AI 補(bǔ)全寫(xiě) SQLScript 時(shí)經(jīng)常要來(lái)回查函數(shù)名、查$ABAP.type()的寫(xiě)法。所以這篇除了講 AMDP 語(yǔ)法實(shí)例還會(huì)給出一套本地 AI 輔助開(kāi)發(fā)工具的配置骨架——用統(tǒng)一的 Key/API 通道把代碼補(bǔ)全接進(jìn)你的編輯器讓寫(xiě) AMDP 時(shí)少翻文檔。核心檢索詞先明確AMDP 語(yǔ)法實(shí)例、AMDP 數(shù)據(jù)庫(kù)存儲(chǔ)過(guò)程、SAP HANA SQLScript。下面從環(huán)境準(zhǔn)備開(kāi)始一步步給出可復(fù)制的配置和可運(yùn)行的 AMDP 代碼。1.1 前置條件清單在動(dòng)手之前確認(rèn)這幾項(xiàng)SAP NetWeaver 7.40 SP08 以上底層是 HANA 數(shù)據(jù)庫(kù)HDB。安裝好 ADT版本建議 3.20 以上能連到你的 ABAP 項(xiàng)目。有一個(gè)可傳輸?shù)拈_(kāi)發(fā)包Package比如ZAMDP_DEMO。本地裝了 VS Code 或 Cursor 之類的編輯器用來(lái)接 AI 補(bǔ)全。AMDP 類只能在 ADT 里開(kāi)發(fā)SAP GUI 里用SE24打開(kāi)只能看不能編輯。這一點(diǎn)先記住后面排障會(huì)用到。1.2 為什么要在本地接 AI 輔助寫(xiě) AMDP 的痛點(diǎn)很集中SQLScript 的函數(shù)名和 ABAP 不一樣DECLARE的類型引用要用$ABAP.type( ... )這種字符串寫(xiě)法游標(biāo)循環(huán)的語(yǔ)法也和普通 ABAP 不同。每次寫(xiě)都要查效率低。把 AI 補(bǔ)全接進(jìn)編輯器后你可以在寫(xiě)DECLARE CURSOR或record_count()時(shí)直接得到提示減少上下文切換。接入方式是用一個(gè)統(tǒng)一的 API 通道把模型能力接到編輯器的補(bǔ)全插件里。下面給出配置骨架。2. TaoToken 前置準(zhǔn)備與統(tǒng)一 Key 通道TaoToken 在這里的角色是一個(gè)統(tǒng)一的模型 API 通道你申請(qǐng)一個(gè) Key就能在本地編輯器、命令行工具里調(diào)用模型做代碼補(bǔ)全和問(wèn)答不用為每個(gè)工具單獨(dú)配一套憑證。官網(wǎng)入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。2.1 申請(qǐng) Key 與確認(rèn)模型 ID登錄后進(jìn)控制臺(tái)創(chuàng)建 API Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。創(chuàng)建完復(fù)制那串 Key只顯示一次。模型 ID 在文檔里能查到常用的編碼模型直接填對(duì)應(yīng) ID 即可文檔地址 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。三個(gè)要素記牢后面所有配置都圍繞它們Base URLhttps://taotoken.net/apiAPI Key你創(chuàng)建的那串Model ID文檔里對(duì)應(yīng)的模型標(biāo)識(shí)2.2 驗(yàn)證 Key 是否可用在正式寫(xiě)配置前先用一條命令確認(rèn) Key 通。打開(kāi)終端curl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer 你的KEY \ -d { model: 你的模型ID, messages: [{role: user, content: 用一句話說(shuō)明AMDP是什么}] }返回里如果choices數(shù)組有內(nèi)容說(shuō)明通道正常。如果返回 401先檢查 Key 有沒(méi)有復(fù)制全、有沒(méi)有多余空格。這一步過(guò)了再往下配編輯器能省很多排查時(shí)間。3. 可復(fù)制配置骨架settings.json 與 config.toml這一節(jié)給兩份可直接復(fù)制的配置。VS Code 系含 Cursor用settings.json命令行編碼工具用config.toml。兩份都遵循同一套 Base URL Key Model ID 三件套。3.1 VS Code / Cursor 的 settings.json如果你用的是支持 OpenAI 兼容接口的補(bǔ)全插件在用戶設(shè)置里加這段。路徑CtrlShiftP→ 輸入Open Settings (JSON)→ 在打開(kāi)的settings.json里追加{ aiAssistant.provider: openai-compatible, aiAssistant.baseUrl: https://taotoken.net/api, aiAssistant.apiKey: 你的KEY, aiAssistant.model: 你的模型ID, aiAssistant.completion.enable: true, aiAssistant.completion.languageOverrides: { abap: true, sql: true } }注意baseUrl結(jié)尾不要帶/v1插件一般會(huì)自己拼。languageOverrides里把a(bǔ)bap和sql打開(kāi)寫(xiě) AMDP 時(shí)補(bǔ)全才會(huì)觸發(fā)。3.2 命令行工具的 config.toml如果你用命令行編碼助手配置放在~/.config/你的工具/config.tomlWindows 在%USERPROFILE%\.config\下[provider] name taotoken base_url https://taotoken.net/api api_key 你的KEY model 你的模型ID [completion] enabled true max_tokens 2048 temperature 0.2 [context] include_extensions [abap, sql, cds]temperature設(shè)低一點(diǎn)代碼補(bǔ)全要的是穩(wěn)定不是發(fā)散。include_extensions把.abap、.sql、.cds都納入上下文寫(xiě) AMDP 時(shí)模型能看到你項(xiàng)目里的相關(guān)文件。3.3 配置生效驗(yàn)證改完配置重啟編輯器。新建一個(gè).abap文件敲DECLARE CURSOR看有沒(méi)有補(bǔ)全彈出。如果沒(méi)有先看插件日志里請(qǐng)求有沒(méi)有發(fā)出去再對(duì)照第 5 節(jié)的報(bào)錯(cuò)排查。4. AMDP 語(yǔ)法實(shí)例與調(diào)用驗(yàn)證配置就緒后進(jìn)入正題。AMDP 的本質(zhì)是一個(gè)實(shí)現(xiàn)了標(biāo)記接口if_amdp_marker_hdb的 ABAP 類方法上用特定關(guān)鍵字修飾方法體里寫(xiě) SQLScript。4.1 定義 AMDP 類骨架在 ADT 里新建 ABAP 類ZCL_AMDP_DEMO定義部分CLASS zcl_amdp_demo DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. INTERFACES if_amdp_marker_hdb. CLASS-METHODS get_flydatas FOR TABLE FUNCTION ztest_tablef. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS.if_amdp_marker_hdb是標(biāo)記接口實(shí)現(xiàn)它才表明這是 AMDP 類。FOR TABLE FUNCTION說(shuō)明這個(gè)方法對(duì)應(yīng)一個(gè) CDS 表函數(shù)。4.2 實(shí)現(xiàn)方法體變量聲明與游標(biāo)循環(huán)實(shí)現(xiàn)部分方法用BY DATABASE FUNCTION FOR HDB LANGUAGE SQLSCRIPT修飾CLASS zcl_amdp_demo IMPLEMENTATION. METHOD get_flydatas BY DATABASE FUNCTION FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING spfli. DECLARE lv_index INT; DECLARE lt_return TABLE ( MANDT $ABAP.TYPE( MANDT ), CARRID $ABAP.TYPE( s_carr_id ), CONNID $ABAP.TYPE( s_conn_id ) ); DECLARE CURSOR lt_spfli FOR ( SELECT * FROM spfli ); lv_index : 1; FOR ls_spfli AS lt_spfli DO lt_return.mandt [:lv_index] : :ls_spfli.mandt; lt_return.carrid[:lv_index] : :ls_spfli.carrid; lt_return.connid[:lv_index] : :ls_spfli.connid; lv_index : :lv_index 1; END FOR; RETURN SELECT mandt, carrid, connid FROM :lt_return; ENDMETHOD. ENDCLASS.幾個(gè)關(guān)鍵點(diǎn)變量用DECLARE類型引用用$ABAP.type( ... )字符串形式賦值用:游標(biāo)用DECLARE CURSOR ... FOR ( SELECT ... )循環(huán)用FOR ... DO ... END FOR內(nèi)表按角標(biāo)賦值lt_return.mandt[:lv_index]。4.3 條件判斷與常用函數(shù)條件判斷和普通 ABAP 類似IF lv_index 1 THEN -- 處理第一行 ELSEIF lv_index 2 THEN -- 處理第二行 ELSE -- 其他 END IF;常用函數(shù)記幾個(gè)record_count( :lt_table )算行數(shù)MOD( :lv_line, 2 )取余CURRENT_DATE/CURRENT_TIME取當(dāng)前日期時(shí)間DAYS_BETWEEN( d1, d2 )算天數(shù)差HOUR()/MINUTE()/SECOND()從時(shí)間取值。4.4 定義 CDS 表函數(shù)并調(diào)用新建 CDS 表函數(shù)ZTEST_TABLEFEndUserText.label: TEST TABLE FUNCTION define table function ZTEST_TABLEF returns { key mandt : abap.clnt; key carrid : s_carr_id; key connid : s_conn_id; } implemented by method zcl_amdp_demoget_flydatas;然后在 ADT 里用Data Preview打開(kāi)這個(gè)表函數(shù)或者寫(xiě)一段 ABAP 調(diào)用SELECT * FROM ztest_tablef INTO TABLE DATA(lt_result). cl_demo_outputdisplay( lt_result ).跑通后能看到SPFLI表里的航班數(shù)據(jù)被游標(biāo)處理后返回。這一步成功說(shuō)明 AMDP 從定義到調(diào)用整條鏈路通了。5. 常見(jiàn)報(bào)錯(cuò)排查寫(xiě) AMDP 和配 AI 通道時(shí)報(bào)錯(cuò)集中在幾個(gè)地方。下面按真實(shí)報(bào)錯(cuò)對(duì)照排查。5.1 401 Unauthorized請(qǐng)求返回 401說(shuō)明 Key 沒(méi)被接受。檢查三處Key 有沒(méi)有復(fù)制完整、Authorization頭是不是Bearer 你的KEY格式、Base URL 有沒(méi)有寫(xiě)錯(cuò)。如果 Key 里帶了換行或空格也會(huì) 401。重新在控制臺(tái)復(fù)制一次粘貼時(shí)注意別帶首尾空白。5.2 local proxy failed編輯器插件報(bào)local proxy failed通常是本地代理端口沒(méi)起來(lái)或者baseUrl填成了帶/v1的地址導(dǎo)致拼接重復(fù)。把baseUrl改回https://taotoken.net/api重啟插件。如果還不行看插件日志里實(shí)際請(qǐng)求的 URL 是什么多半是路徑拼錯(cuò)了。5.3 reading choices 報(bào)錯(cuò)返回體解析時(shí)報(bào)reading choices相關(guān)錯(cuò)誤一般是響應(yīng)結(jié)構(gòu)和你用的插件預(yù)期不一致。先確認(rèn)請(qǐng)求里model字段填的是文檔里存在的模型 ID不是隨便寫(xiě)的名字。模型 ID 錯(cuò)了返回體里沒(méi)有choices插件解析就崩。對(duì)照文檔核對(duì)模型 ID。5.4 OAuth 相關(guān)報(bào)錯(cuò)如果插件走的是 OAuth 流程而不是 API Key報(bào) OAuth 錯(cuò)誤說(shuō)明認(rèn)證方式選錯(cuò)了。在插件設(shè)置里把認(rèn)證方式切成 API Key填 Base URL Key Model ID 三件套。OAuth 那套不適用于這種直連 API 的場(chǎng)景。5.5 AMDP 側(cè)常見(jiàn)錯(cuò)誤METHOD ... is not an AMDP method檢查類有沒(méi)有實(shí)現(xiàn)if_amdp_marker_hdb方法有沒(méi)有加BY DATABASE ...修飾。Table SPFLI is not usedUSING后面沒(méi)聲明用到的表。AMDP 方法里訪問(wèn)的表必須在USING里列出。Syntax error in SQLScript多半是$ABAP.type()的引號(hào)寫(xiě)錯(cuò)或者變量引用忘了加冒號(hào):lv_var。SQLScript 里引用 ABAP 變量要加冒號(hào)。6. 繼續(xù)深入的方向AMDP 的BY DATABASE PROCEDURE和BY DATABASE FUNCTION兩種模式用途不同前者標(biāo)記為存儲(chǔ)過(guò)程可以寫(xiě)更復(fù)雜的邏輯后者標(biāo)記為表函數(shù)主要給 CDS 消費(fèi)。方法嵌套調(diào)用時(shí)被調(diào)用的 AMDP 方法也要在USING里聲明方法名大寫(xiě)。如果你要把這套 AI 輔助長(zhǎng)期用在日常編碼里可以考慮 Coding Plan地址 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 適合需要持續(xù)補(bǔ)全和 Agent 輔助的場(chǎng)景。只想先驗(yàn)證模型對(duì)話效果用模型對(duì)話入口 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 試幾句。Key 管理和接入文檔分別在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 和 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。最后給個(gè)實(shí)操建議AMDP 調(diào)試時(shí)先在 ADT 里用Data Preview單獨(dú)跑表函數(shù)確認(rèn) SQLScript 邏輯對(duì)了再接到 ABAP 程序里調(diào)用。這樣出錯(cuò)時(shí)能快速定位是 SQLScript 的問(wèn)題還是 ABAP 調(diào)用的問(wèn)題。寫(xiě)游標(biāo)循環(huán)時(shí)lv_index的初始化和自增別漏漏了會(huì)死循環(huán)或者只處理一行。