ABAP学习笔记之——第三章:OPEN SQL和NATIVE SQL

news2025/2/28 12:38:04

一、SAP R/3体系结构

        SAP R/3一个分为三层:数据库层、应用层、表示层。其中应用层和数据库层由一个系统构成。

表示层:表示层(Presentation Layer)简单来讲其实就是指个人PC,是保存构成SAPGUI(GraphicalUserInterface)的软件组件(Software Component)的机器。在这个层次提供 R/3 系统与用户之间的接口。SAPGUI是指安装在个人PC上的终端设备,用户就通过此设备输入或者查询数据。

应用层:SAP所有的程序都在应用层执行,SAP GUI只是起到终端的作用,运营服务器的应用层由一个或多个应用服务器与一个文档服务器(Message Server)组成。通过文档服务器与应用服务器相互连接,使用户自动选择符合小的服务器登录。其中可以使用多个应用服务器分散系统的负荷。SAP 中的应用层上存在本地缓冲器,若在 ABAP 数据字典中的数据库表上设置缓冲器,则不访问数据库层而直接在本地缓冲器中读取数据。这种设置可以提高SAP 性能,但只适用于 OPEN SOL。分配器(Dispatcher) 用于适当地分配工作流( Work Process

数据库层:数据库层(Database Layer) 与本章要学习的 SQL 语密切关系,SAP 中的所有数据都存储在这一层即数据库存储主数据,事务码以及 R/3 系统的所有数据。在应用层上创建用户与画面相互作用(Dialog)的 GU,它主要负责查询/维护数据库层的数据。在数据库层通过 DBMS 可以创建和管理如数据库表/视图/结构体等数据库对象。在这种环境下,开发者通过应用程序的 GU画面修改数据或者直接连接到数据库执行 SOL。

        SAP 禁止一般用户直接连接数据库修改数据,甚至有时还限制查询数据的权限。这种设置是为了保障数据的完整性、一贯性、安全性及透明性。当然,如果公开数据库的系统信息、ID 及密码就无法完全切断直接访问数据库的渠道。如图所示,ABAP 开发者通过ABAP数据字典管理数据库结构。

        ABAP 程序中使用的对象 (数据表、视图、结构体、类型等) 称为 ABAP 数据字典这些对象的信息叫 Metadata、Data Definition 或者 Schema,另外,通过这些ABAP 数据字典来定义及管理数据结构。 

二、OPEN SQL

读取数据:

 INTO:当查询一条数据时使用结构体、变量、工作区;当查询多条数据时使用内表,往内表插入数据是要使用append。

Package size:一次性读取n条数据。需要使用endselect语句。

From:

 Where:

例1(常规查询):

DATA:gt_itab TYPE STANDARD TABLE OF sflight,
     gs_wa   TYPE sflight.

*查询出来的结果放入结构体
SELECT * INTO gs_wa FROM sflight WHERE carrid = 'AA'.
  WRITE:/ gs_wa-carrid,gs_wa-connid.
ENDSELECT.
WRITE / '--------------------------------这里是分界线-----------------------------------'.
*查询结果用内表保存
SELECT * INTO TABLE gt_itab FROM sflight WHERE carrid = 'AA'.
LOOP AT gt_itab INTO gs_wa. "利用loop循环遍历输出
  WRITE:
  / gs_wa-carrid,gs_wa-connid.
ENDLOOP.

例2(动态sql-查询字段):

*动态SQL语句
DATA:gs_line(72) TYPE c,
     gt_list     LIKE TABLE OF gs_line(72).
gs_line = 'CARRID CONNID'.
SELECT DISTINCT (gs_line) INTO TABLE gt_itab
  FROM sflight WHERE CARRID = 'AA'.
IF sy-subrc = 0.
  LOOP AT gt_itab INTO gs_wa.
    WRITE: / gs_wa-carrid,gs_wa-connid.
  ENDLOOP.
ENDIF.

例3(package):

*package一次性取出n条数据循环输出
DATA NUM TYPE I VALUE 1.
SELECT carrid connid
  FROM spfli
  INTO CORRESPONDING FIELDS OF TABLE gt_itab
  PACKAGE SIZE 5.
  WRITE: / '第',NUM,'次取出的数据'.
  NUM = NUM + 1.
  LOOP AT gt_itab INTO gs_wa.
    WRITE: / gs_wa-carrid,gs_wa-connid.
  ENDLOOP.
ENDSELECT.

例4(动态使用数据库表名称):

*动态使用数据库名称
PARAMETERS p_tname TYPE char10.
DATA gs_wa TYPE sflight.

SELECT SINGLE * INTO gs_wa FROM (p_tname)
  WHERE carrid = 'AA'.
  WRITE:/ gs_wa-carrid,gs_wa-connid.

例5(INNER JOIN使用方法):

*INNER JOIN使用方法
TYPES: BEGIN OF t_str,
         carrid   TYPE sflight-carrid,
         carrname TYPE scarr-carrname,
       END OF t_str.
DATA:gs_str TYPE t_str.
SELECT SINGLE a~carrid b~carrname
  INTO CORRESPONDING FIELDS OF gs_str
  FROM sflight AS a
  INNER JOIN scarr AS b
  ON a~carrid = b~carrid
  WHERE a~carrid = 'AA'.
WRITE : gs_str-carrid,gs_str-carrname.

例6(outer join使用方法):

*outer join使用方法
TYPES : BEGIN OF t_str,
          carrid   TYPE sflight-carrid,
          carrname TYPE scarr-carrname,
        END OF t_str.
DATA:gs_str TYPE t_str.
SELECT SINGLE a~carrid b~carrname
  INTO CORRESPONDING FIELDS OF gs_str
  FROM sflight AS a
  LEFT JOIN scarr AS b
  ON a~carriD = b~carrid
  WHERE a~carrid = 'AA'.
WRITE: gs_str-carrid,gs_str-carrname.

例7(动态设置筛选条件):

*动态设置查询条件
DATA gs_where TYPE c LENGTH 72.
DATA gv_carrname TYPE scarr-carrname.
PARAMETERS carrid TYPE scarr-carrid.
CONCATENATE 'CARRID = ''' carrid '''' INTO gs_where. "拼接字符串:CARRID = 'AC'.
SELECT SINGLE carrname
  INTO gv_carrname
  FROM scarr
  WHERE (gs_where).
WRITE / gv_carrname.

例8(动态设置多个筛选条件):

*两个动态参数
TYPES : BEGIN OF gs_carr,    "自定义结构体
          carrid   TYPE scarr-carrid,
          carrname TYPE scarr-carrname,
        END OF gs_carr.
DATA gs_where TYPE c LENGTH 72.
DATA gt_where LIKE TABLE OF gs_where.
DATA gT_carr TYPE gs_carr.    "实例化结构体
PARAMETERS carrid1 TYPE scarr-carrid.
PARAMETERS carrid2 TYPE scarr-carrid.

CONCATENATE 'CARRID = ''' carrid1 '''' INTO gs_where.
APPEND gs_where TO gt_where.
gs_where = 'OR'.
APPEND gs_where TO gt_where.
CONCATENATE 'CARRID = ''' carrid2 '''' INTO gs_where.
APPEND gs_where TO gt_where.          "字符串拼接

SELECT *
  INTO CORRESPONDING FIELDS OF gT_carr "结果输出到结构体中(自动找到重名的字段进行赋值)
  FROM scarr
  WHERE (gt_where).
  WRITE: / gT_carr-carrid,gt_carr-carrname.
ENDSELECT.

例(在gui上执行sql语句):

PARAMETERS :p_sql(255) TYPE c.

DATA: go_sql TYPE REF TO cl_sql_statement.   "cl_sql_statement是一个类
DATA: gv_sql TYPE string.
DATA: gd_ret TYPE i.

CREATE OBJECT go_sql.
gv_sql = p_sql.

TRANSLATE gv_sql TO UPPER CASE.

CALL METHOD go_sql->execute_update     "execute_update是cl_sql_statement类的一个方法
  EXPORTING
    statement      = gv_sql   "输入SQL语句
  RECEIVING
    rows_processed = gd_ret.   "接收数据

WRITE: / '影响条数', gd_ret.

FOR ALL ENTRIES:FOR ALL ENTRY 语句与套 SELECT 语或 Subquery 的能相似。使用 FOR ALLENTRY 语句时,WHERE 语句中使用的条件必须是 itab 中存在的字段。

例:

*FOR ALL ENTRIES语句使用
DATA gt_spfli TYPE TABLE OF spfli.
DATA gt_sflight TYPE TABLE OF sflight.
DATA gs_sflight TYPE sflight.

SELECT * FROM spfli INTO TABLE gt_spfli.   "供下面做查询表用
SELECT * FROM sflight INTO TABLE gt_sflight
  FOR ALL ENTRIES IN gt_spfli   "从上面查询出来的数据作为表继续查询
  WHERE carrid = gt_spfli-carrid
  AND connid = gt_spfli-connid.

LOOP AT gt_sflight INTO gs_sflight.
  WRITE: / gs_sflight-carrid,gs_sflight-connid.
ENDLOOP.

 Group by:分组函数(having)

例:

*GROUP BY 语句使用
DATA:gv_carrid     TYPE sflight-carrid,
     gv_connid     TYPE sflight-connid,
     gv_paymentsum TYPE i.
SELECT carrid connid AVG( paymentsum )
  INTO (gv_carrid,gv_connid,gv_paymentsum)
  FROM sflight GROUP BY carrid connid.

  WRITE: / gv_carrid,gv_connid,gv_paymentsum.
ENDSELECT.

Order by:排序。用 ASCENDING升序,DESCENDING 降序

- 根据表的 KEY 值进行排序。

- 只适用于SELECT*语句。

- 在JOIN 语和视图中无法使用。

例:

*HAVING \ ORDER BY语句使用
SELECT carrid connid AVG( paymentsum ) AS pay
  INTO (gv_carrid,gv_connid,gv_paymentsum)
  FROM sflight GROUP BY carrid connid
  HAVING AVG( paymentsum ) > 40000
  ORDER BY pay.
  WRITE: / gv_carrid,gv_connid,gv_paymentsum.
ENDSELECT.

Subquery:利用 Subquery 可以在 WHERE 语句中追加特殊条件。Subquery 的 SELECT 语中只能指定一个字段。

例:

*SUBQUERY 用法
DATA:gv_carrid     TYPE sflight-carrid,
     gv_connid     TYPE sflight-connid,
     gv_paymentsum TYPE sflight-paymentsum.

SELECT SINGLE CARRID CONNID PAYMENTSUM
  INTO (gv_carrid,gv_connid,gv_paymentsum)
  FROM SFLIGHT AS A
  WHERE CARRID IN
  ( SELECT CARRID FROM SPFLI
    WHERE CARRID = A~CARRID AND CONNID = A~CONNID
  )
  AND A~CARRID = 'AA'.
  WRITE: / gv_carrid,gv_connid,gv_paymentsum.

 修改数据:

Insert:

插入一条数据:

插入多条数据:往数据库表一次性插入内表的所有值。插入相同主键的数据时会发生 dump error,为了避免发生这种错误要使用ACCEPTING DUPLICATE KEYS 语。INSERT 语执行失败系统变量SY-SUBRC会返回4。

例:

*插入多条数据
DATA : gt_spfli TYPE TABLE OF spfli,
       gs_spfli TYPE spfli.

gs_spfli-carrid = 'CN'.
GS_spfli-connid = '001'.
gs_spfli-cityfrom = 'Beijing'.
gs_spfli-cityto = 'Seoul'.
APPEND gs_spfli TO gt_spfli.

gs_spfli-carrid = 'CN'.
GS_spfli-connid = '002'.
gs_spfli-cityfrom = 'Beijing'.
gs_spfli-cityto = 'Busan'.
APPEND gs_spfli TO gt_spfli.

INSERT spfli FROM TABLE gt_spfli ACCEPTING DUPLICATE KEYS.

Update:

修改一条数据:

修改多条数据:

 例:

DATA gs_spfli TYPE spfli.
MOVE 'CN' TO gs_spfli-carrid.
MOVE '011' TO gs_spfli-connid.
MOVE 'shanghai' TO gs_spfli-cityfrom.
*一条数据
update spfli from gs_spfli.
UPDATE spfli SET cityto = 'beijing'
*多条数据
WHERE carrid = 'CN' AND connid = '001'.
IF sy-subrc = 0.
  WRITE 'update is success!!!'.
ENDIF.

Delete:

删除一条数据:

 删除多条数据:

例:

DATA gs_spfli TYPE spfli.

gs_spfli = 'CN'.

DELETE spfli FROM gs_spfli.

DELETE FROM spfli WHERE carrid = 'CN'.
IF sy-subrc = 0.
  WRITE 'delete success.'.
ENDIF.

Modify:

MODIFY 既有 UPDATE 功能也有INSERT功能。当数据库表中存在该值时会以主键为基准更新此数据,若不存在则会插入此数据。可以插入/更新一条或多条数据,<target>用于指定数据库表名字使用时还可以动态地定义。

一条数据:

多条数据:

例:

DATA:gt_spfli TYPE TABLE OF spfli,
     gs_spfli TYPE spfli.
*一条数据
gs_spfli-carrid = 'CN'.
gs_spfli-connid = '001'.
gs_spfli-cityfrom = 'BEIJING'.
MODIFY spfli FROM gs_spfli.
*多条数据
gs_spfli-carrid = 'CN'.
gs_spfli-connid = '001'.
gs_spfli-cityfrom = 'shanghai'.
APPEND gs_spfli TO gt_spfli.

gs_spfli-carrid = 'CN'.
gs_spfli-connid = '003'.
gs_spfli-cityfrom = 'shanghai'.
APPEND gs_spfli TO gt_spfli.

MODIFY spfli FROM TABLE gt_spfli.

 三、 NATIVE SQL

简介:OPEN SQL 不管使用任何数据库类型(Oracle、Informix、DB2 等),其语法都相同,而NATIVE SOL 随着数据库类型的不同其相应的 SQL 语也有所差异。NATIVE SOL 是适用于 Oracle 数据库的,因此若设置了 MS SOL等其他数据库的话就不能正常执行。在ABAP 程序中 NATIVE SOL 虽然没有 OPEN SOL 使用频繁,但是可以实现使用OPEN SQL 无法实现的复杂的 SQL 语句。

优点:可以访问 ABAP 数据库中没有的数据库表(Oracle 系统数据表等)。是依赖于数据库的SOL 语句,因此可以实现在 OPEN SOL中无法实现的 SOI

缺点:无法鉴定(Syntax Check)EXEC ~ ENDEXEC 之间的语法,因此常会发生 Dump Error。在使用不同数据库的系统中无法使用含有 NATIVE SQL 的ABAP 程序。在 SQL 语中一定要追加用于区分客户的 mandt 字段。

语法:

NATIVE SQL 随着使用不同的数据库类型其 SQL 语也有所差异。基本语句以 EXECSQL.开头、以ENDEXEC.结束。使用变量时要在变量名前追加冒号“.”,另外,NATIVE SOI中一定要追加区分客户的MANDT 字段。

 简单查询:

*简单查询
DATA: gv_carrid LIKE sflight-carrid VALUE 'AA',
      gv_connid LIKE sflight-connid.

"into要空格后再接冒号
EXEC SQL.
  select a.connid
    into :gv_connid
    from sflight a
    where a.mandt = :sy-mandt and a.carrid = :gv_carrid
ENDEXEC.

WRITE gv_connid.

 performing 用法:

TYPES: BEGIN OF t_str,
         carrid LIKE sflight-carrid,
         connid LIKE sflight-connid,
       END OF t_str.

DATA gt_itab TYPE TABLE OF t_str.
DATA gs_wa TYPE t_str.
DATA gv_carrid LIKE sflight-carrid VALUE 'AA'.

EXEC SQL PERFORMING append_itab.
  select a.carrid,a.connid
    into :gs_wa-carrid,:gs_wa-connid
    from sflight a
    where a.mandt = :sy-mandt
    and a.carrid = :gv_carrid
ENDEXEC.

FORM append_itab.
  WRITE: / gs_wa-carrid,gs_wa-connid.
  APPEND gs_wa TO gt_itab.
  CLEAR gt_itab.
ENDFORM.

多表连接:

TYPES: BEGIN OF t_str,
         carrid   LIKE sflight-carrid,
         connid   LIKE sflight-connid,
         carrname LIKE scarr-carrname,
       END OF t_str.
DATA gs_wa TYPE t_str.
DATA: gv_carrid LIKE sflight-carrid VALUE 'AA'.

EXEC SQL PERFORMING write_data.
  select a.carrid,b.carrname
  into :gs_wa-carrid,:gs_wa-connid
  from sflight a,scarr b
  where a.mandt = b.mandt
    and a.carrid = b.carrid
    and a.mandt = :sy-mandt
    and a.carrid = :gv_carrid
ENDEXEC.

FORM write_data.
  WRITE: / gs_wa-carrid,gs_wa-carrname.
ENDFORM.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/39030.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字验证学习笔记——SystemVerilog芯片验证10 ——类的成员

一、类和成员 类是成员变量和成员方法的载体&#xff0c;之所以称为自洽体&#xff0c;是因为其变量和方法应符合‘聚拢’原则&#xff0c;即一个类的功能应该尽可能简单&#xff0c;不应承担过多的职责&#xff0c;更不应该承担不符合它的职责&#xff0c;这在设计模式被称为…

变分自编码器(VAES)

Dimensionality reduction ,PCA and autoencoders Dimensionality reduction 我们清楚&#xff0c;数据降维其实都是减少数据的特征数量&#xff0c;如果把encoderencoderencoder看作是由高维原有特征生成低维新特征的过程。把decoderdecoderdecoder看作是将低维特征还原为高…

vulnhub靶机ha:wordy

靶机下载链接&#xff1a;HA: Wordy ~ VulnHub 靶机ip&#xff1a;192.168.174.136&#xff08;后面重启后变成192.168.174.137&#xff09; kali ip&#xff1a;192.168.174.128 目录 靶机ip发现: 靶机端口扫描: 子目录扫描&#xff1a; wpscan扫描 漏洞利用1 漏洞利…

ASEMI肖特基二极管MBR40200PT参数,MBR40200PT规格

编辑-Z ASEMI肖特基二极管MBR40200PT参数&#xff1a; 型号&#xff1a;MBR40200PT 最大重复峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;200V 最大平均正向整流输出电流&#xff08;IF&#xff09;&#xff1a;40A 峰值正向浪涌电流&#xff08;IFSM&#xff0…

5、Mybatis的查询功能(必定有返回值)

Mybatis的查询功能&#xff08;必定有返回值&#xff09; 注意&#xff1a; 查询功能与前面的增删改不同&#xff0c;增删改的返回值是固定的&#xff08;所以增删改我们就有两种返回值要么设置为int获取受影响的行数&#xff0c;要么设置为void我们不获取返回值&#xff09;…

基于JAVA的农产品生鲜销售管理系统【数据库设计、源码、开题报告】

数据库脚本下载地址&#xff1a; https://download.csdn.net/download/itrjxxs_com/86468222 主要使用技术 Struts2HibernateJSPJSCSSMysql 功能介绍 1&#xff0c;游客访问 |–系统首页&#xff0c;查看商品列表 |–特价商品 |–最新上架 2&#xff0c;会员访问 |–用户登…

Qt 界面设置无边框之后如何实现缩放界面

在qt中&#xff0c;如果设置的了窗口无边框的话&#xff08;即setWindowFlag(Qt::FramelessWindowHint);&#xff09;那么窗口就没法直接被鼠标拖动了&#xff0c;也没法按住窗口的边界进行缩放。 如果要实现缩放和拖动&#xff0c;一般来说就需要的重写窗口类的mousePressEve…

目标检测论文解读复现之十九:基于YOLOv5网络模型的人员口罩佩戴实时检测

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0…

8.3 数据结构——交换排序

基本思想&#xff1a;两两比较&#xff0c;如果发生逆序则交换&#xff0c;直到所有记录都排好序为止。 常见的交换排序&#xff1a;&#xff08;1&#xff09;冒泡排序 &#xff08;2&#xff09;快速排序 8.3.1 冒泡排序 基本思想&#xff1a;每趟不断将记录两两比较&…

VLAN(Virtual LAN)虚拟局域网

1、广播与广播域 广播&#xff1a;将广播地址做为目标地址的数据帧 广播域&#xff1a;网络中能接收到同一个广播所有节点的集合&#xff08;广播域越小越好&#xff0c;收到的垃圾广播越少&#xff0c;这样通信效率更高&#xff09; MAC地址广播 广播地址为&#xff1a;FF-FF-…

rabbitmq配置windows authentication(windows account)登录

rabbitmq配置windows authentication(windows account开启插件配置文件创建一个不需要密码的账号&#xff0c;赋予administrator权限。用windows账号和密码登录rabbitmq加密明文密码创建密钥的文件,添加密钥字符串加密解密用户名密码配置加密后的字符串重启rabbitmq&#xff0c…

HyperLynx(三十一)高速串行总线仿真(三)

高速串行总线仿真&#xff08;三&#xff09; 1.从一个多层板工程中验证串行通道 2.在多层板中设置连接器模型 1.从一个多层板工程中验证串行通道 在本例练习中&#xff0c;将集中研究从芯片到插件形成的串行发射通道&#xff0c;并分析它的性能。 (1)打开 HyperLynx 软件&a…

Centos下安装postgreSQL

最近北京yq严重&#xff0c;在家学习下postgreSQL &#xff0c;本次使用的是 Centos 环境安装是有&#xff0c;记录下来&#xff0c;方便备查。 第一步、下载与安装 下载地址&#xff1a;postgreSQL官网 在官网上选择 Linux系统&#xff0c;使用 yum来下载软件&#xff0c;只…

SpringBoot SpringBoot 原理篇 1 自动配置 1.11 bean 的加载控制【编程式】

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 原理篇 文章目录SpringBootSpringBoot 原理篇1 自动配置1.11 bean 的加载控制【编程式】1.11.1 bean 的加载控制1.11.2 环境…

[附源码]Python计算机毕业设计高校辅导员工作管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

现代密码学导论-15-多明文加密

目录 3.4更强的安全观念 3.4.1 多明文加密安全 多消息窃听实验 DEFINITION 3.18 多明文加密下的不可区分性 PROPOSITION 3.19 定义3.18强于定义3.8的事实证明 PROPOSITION 3.19 的证明 概率加密的必要性 THEOREM 3.20 3.4更强的安全观念 到目前为止&#xff0c;我们一…

MySQL 慢查询日志 使用方法浅析 日志定位与优化技巧

目录 前言 1、如何开启使用慢查询日志&#xff1f; 1.1 开启慢查询日志 1.2 设置慢查询阈值 1.3 确定慢查询日志的文件名和路径 1.3.1 查询MySQL数据目录 1.3.2 查询慢查询日志文件名 1.3.3 查询全局设置变量 1.3.4 查询单个变量命令 1.3.5 其他注意事项 2、如何定位并优…

备战2023蓝桥国赛-重新理解Prim和Kruskal算法

备战2023蓝桥国赛-重新理解Prim和Kruskal算法Prim算法Kruskal算法Prim算法 题目描述&#xff1a; 解析&#xff1a; prim算法跟dijkstra的朴素解法有很多相像部分&#xff0c;他们都是枚举中继节点来更新下一个节点&#xff0c;都是选最小的dist值来更新&#xff0c;时间复杂…

【线性表】—动态顺序表的增删查改实现

小菜坤日常上传gitee代码&#xff1a;https://gitee.com/qi-dunyan&#xff08;所有的原码都放在了我上面的gitee仓库里&#xff09; 数据结构知识点存放在专栏【数据结构】后续会持续更新 ❤❤❤ 个人简介&#xff1a;双一流非科班的一名小白&#xff0c;期待与各位大佬一起努…

【网页设计】期末大作业html+css(动漫网站)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…